416. Partition Equal Subset Sum

第一反应是建立PQ,多退少补,但是在达到目的前,没法确定某一个元素该在哪边,操作起来很困难。
看了提示是DP,大概明白了。

target是总和的/2,当然如果综合是奇数就直接GG思密达了。

双层遍历,外层nums[i]的所有元素遍历,内层是从0-(i-1)组成的所有组合,加上当前nums[i]组成新的组合,如果新的组合的和是target就找到了,说明从nums[0] - nums[i]的这些元素里有可能挑出某些数,达到target,那就OK了。

416. Partition Equal Subset Sum

做之前怂了,看了眼讨论,有两种,因为剪枝情况很多,DFS也可以;用DP的和这个思路差不多,但是人家明显多想了很多情况,比如某一个元素nums[i]>target就GG了,可以直接停止搜索。

(https://discuss.leetcode.com/topic/62307/java-short-dp-solution-with-explanation)

这个DP的解释就挺好的。

public class Solution 
{
    public boolean canPartition(int[] nums) 
    {
        if(nums.length == 0) return true;
        
        int total = 0;
        for(int i: nums) total+=i;
        if(total%2 !=0) return false;
        
        boolean[] dp = new boolean[total/2]; // there is a subset which sums to i
        int curMax = nums[0];                // we dont have to go through the entire dp[], stop at current max sum
        for(int i = 0; i < nums.length;i++)
        {
            
            if(nums[i] > total/2) return false;
            if(nums[i] == total/2) return true;
            dp[nums[i]] = true;
            for(int j = 1; j <= curMax;j++)
            {
                if(dp[j] && j+i <= total/2)
                {
                    if(j+i == total/2) return true;
                    dp[j+i] = true;
                    curMax = Math.max(j+i,curMax);
                }
            }
        }
        
        return false;
    }
}