【leetCode-DFS】【leetCode-DP-01揹包】279. 完全平方數

      給定一個非負整數數組,a1, a2, ..., an, 和一個目標數,S。現在你有兩個符號 + 和 -。對於數組中的任意一個整數,你都可以從 + 或 -中選擇一個符號添加在前面。

返回可以使最終數組和爲目標數 S 的所有添加符號的方法數。

示例 1:

輸入: nums: [1, 1, 1, 1, 1], S: 3
輸出: 5
解釋: 

-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3

一共有5種方法讓最終目標和爲3。


注意:

數組非空,且長度不會超過20。
初始的數組的和不會超過1000。
保證返回的最終結果能被32位整數存下。

暴力搜索所有數+或-的狀態

    private static int ccnt = 0;
    public static int findTargetSumWays(int[] nums, int S) {
        getSum(nums,0,S);
        return ccnt;
    }

    private static void getSum(int[] nums,int i,int S) {
        if(i == nums.length){
            if(0 == S){
                ccnt++;
            }
            return ;
        }

        getSum(nums,i + 1,S + nums[i]);
        getSum(nums,i + 1,S - nums[i]);
    }

優化

可以轉化爲01揹包問題。

定義S(P)+ S(N) = C 其中S(p) 是集合中的正數集合 而S(N)是集合中的負數集合 而T是集合中的全部數據集
而 S(P)- S(N) = S(目標值) 其中 S是 目標值
S(P) - S(N) + (S(P)+ S(N) )  = S + (S(P)+ S(N) ) ==> 2S(P) = S+C ==> S(P) = (S+C) >> 1

定義:dp[i]代表遍歷到數組第i個數的時候能組成目標數值的種類個數

初始化: dp[0] = 1

狀態轉移方程: dp[j] = dp[j] + dp[j-nums[i]]

    public static int findTargetSumWays_OPT(int[] nums, int S) {
        
        int len = nums.length;
        int sum = 0;
        for(int  i = 0;i < len;i++) {
            sum += nums[i];
        }
        int tar = sum + S;
        if(tar % 2==1 || sum < S) {
            return 0;
        }
        tar /=2;
        int[] dp = new int[tar+1]; // 定義dp[i]爲 第i個數的時候和爲S的方法數
        dp[0] = 1;
        for(int i = 0;i < len;i++) {
            for(int j = tar;j >= nums[i] ;j--) {
                dp[j] +=  dp[j - nums[i]] ;
            }
        }
        return dp[tar];
    }

 

發佈了615 篇原創文章 · 獲贊 110 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章