Leetour-416 split equal sum subset (dp)

Leetour-416 split and subset

1. Topic

You are given a non- empty array nums containing only positive integers. Please judge whether this array can be divided into two subsets so that the sum of the elements of the two subsets is equal.

Example 1:

Input: nums = [1,5,11,5]
Output: true
Explanation: The array can be split into [1, 5, 5] and [11].
Example 2:

Input: nums = [1,2,3,5]
Output: false
Explanation: The array cannot be split into two-element and equal subsets.

hint:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 100

2. Analysis

  1. question. Judging whether it can be divided into two and equal subsets, at a glance, we can know that there are two subsets, and the sum of each subset is sum/2 . First, it is divided into subsets, and we can know that the backtracking method can carry out all The subsets are all obtained, but it is often an exponential time complexity, so we can think of dynamic programming to solve it here .
  2. What about dynamic programming is the 01 knapsack problem . We can understand this problem as requiring i items to be put into a knapsack with a capacity of sum/2 . The weight and value of the i item are weight[i]=value[ i]=nums[i]. And each item can only be put in once , so we can use the 01 backpack idea to solve it.
  3. The return value, when we store all the items in the backpack and get the maximum value, we can judge whether the value is equal to sum/2 , if it is equal, then the rest is another subset, which can be judged success.
  4. other details. Because the sum of each subset is sum/2, if the sum is an odd number , it must not be divided into two equal heaps. This can be used because we need to find out the sum value. If the largest number in the nums array is larger than sum/2, it is of course not possible, but this needs to be sorted, which increases the time complexity, so it is not used.
  5. The code solves the 01 knapsack problem by traversing the one-bit array backwards.

3. Code and comments

class Solution {
    
    
    public boolean canPartition(int[] nums) {
    
    
        // 1.背包容量为sum/2
        // 2.看成01背包问题,weight[i]=value[i]
        // 3.背包中每一个元素不能被重复放入
        // 4.等到我们找到sum/2的值等于sum/2是,我们即可进行判断
        int sum = 0;
        for (int i = 0; i < nums.length; i++){
    
    
            sum += nums[i];
        }
        if (sum % 2 == 1) return false;
        // 5.dp[i]表示背包容量为i时,最大的价值
        int[] dp = new int[sum/2 + 1];
        for (int i = 0; i < nums.length; i++){
    
    
            // 6.最大容量为sum/2,更新值到最小当前的nums[i],再小的话就与之前一样,不需要进行更改。
            for (int j = sum/2; j >= nums[i]; j--){
    
    
                dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }
        return dp[sum/2] == sum/2;
    }
}

4. Practice

Leetcode topic link: https://leetcode.cn/problems/partition-equal-subset-sum/

Guess you like

Origin blog.csdn.net/qq_51326491/article/details/129265960