第一反应是建立PQ,多退少补,但是在达到目的前,没法确定某一个元素该在哪边,操作起来很困难。
看了提示是DP,大概明白了。
target是总和的/2,当然如果综合是奇数就直接GG思密达了。
双层遍历,外层nums[i]的所有元素遍历,内层是从0-(i-1)组成的所有组合,加上当前nums[i]组成新的组合,如果新的组合的和是target就找到了,说明从nums[0] - nums[i]的这些元素里有可能挑出某些数,达到target,那就OK了。
做之前怂了,看了眼讨论,有两种,因为剪枝情况很多,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;
}
}