1. 程式人生 > 實用技巧 >leetcode [416. 分割等和子集]

leetcode [416. 分割等和子集]

(https://leetcode-cn.com/problems/partition-equal-subset-sum/)

看完題之後我們應該可以把問題轉化一下:假設nums陣列和為sum,如果sum為奇數,就直接false了,否則另target = sum/2。這樣問題就轉化成了:在nums陣列中能否找到某些數,使他們的和為target

最直接的想法就是dfs,暴力去搜,但看了看資料規模,dfs的複雜度是2^n,好像不太行

菜菜的我就止步於此了,看答案發現解法是動態規劃,其實就是01揹包,揹包的最大容量在這一題中變成了target而已,揹包九講中說到01揹包中dp[i] [j] 的定義是:前i個物品恰好裝進容量為j的揹包內所能獲得的最大價值。

/*
    在陣列中找出一些數,使他們的和等於 target
    除了dfs有沒有其他的方法?
*/
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int mx = 0,sum = 0, n = nums.size();
        for (int i = 0; i < n; i++){
            sum += nums[i];
            mx = max(mx, nums[i]);
        }
        if (sum % 2 || mx > (sum/2)) return false;
        if (mx == sum / 2) return true;
        int target = sum / 2;
        vector<vector<int>> dp(n+1, vector<int>(target+1,false));
        dp[0][0] = true;
        for (int i = 1; i <= n; i++){
            //cout<<i<<endl;
            for (int j = 0; j <= target; j++){
                dp[i][j] = dp[i][j] || dp[i-1][j];
                if (j >= nums[i-1])  dp[i][j] = dp[i][j] || dp[i-1][j-nums[i-1]];
            }
        }
        return dp[n][target];
    }
};

然後就按部就班的寫完了,寫完之後先是感到空虛(可能因為沒有仔細思考),然後自己就在想:我也做過一些動態規劃的題目,雖然01揹包問題怎麼做我給忘了,但翻翻部落格也是很快的就撿起來了,但我在看這題的時候根本沒有往dp上去想;那麼在實際拿到一個題的時候,該如何判斷這題可以往dp上想呢?

我覺得1.就是多做題而產生的題感

​ 2.發現好像用dfs去解時間不太允許的時候,就可以考慮用dp(我也不知道對不對(逃)