[LeetCode] 416. Partition Equal Subset Sum

题:https://leetcode.com/problems/partition-equal-subset-sum/

题目大意

数组nums中只有正数,求是否能将nums中的元素放到两个集合中,使得两个集合中的元素和相同。

思路

方法一 dfs

对于使用 dfs 分为 两个 集合,若其中有一个 成功返回 true

具体做法是 在递归的过程中 ,分别将 num 加入 不同的 集合中,若 有某一个 集合 成功,那么另一个就会成功。

但是 这个方法 在 java 中 会超时

这是由于 当 nums 从小到大排序时,target[i]>=nums[index] 这个条件 会递归到很多层后才会发生作用,也就是 剪枝在 整个树 的 底部。

我们改进的方法是 在nums中 从大到小访问数据,这样会 使得 target[i]>=nums[index] 条件更早发生。

超时版本

class Solution {
    public boolean dfs(int[]nums,int index, int[] target){
        for(int i = 0 ; i < 2 ; i++){
            if(target[i]>=nums[index]){
                target[i] = target[i] - nums[index];
                if(target[i] == 0 || dfs(nums,index+1,target))
                    return true;
                target[i] = target[i] + nums[index];
            }
        }
        return false;
    }
    
    
    public boolean canPartition(int[] nums) {
        int _sum = 0;
        for(int num:nums)
            _sum += num;
        if((_sum&1) == 1)
            return false;
        _sum = _sum>>1;
        int[] target = {_sum,_sum};
        return dfs(nums,0,target);
    }
}

Your runtime beats 98.40 % of java submissions.

甚至好于 dp

class Solution {
    public boolean dfs(int[]nums,int index, int[] target){
        for(int i = 0 ; i < 2 ; i++){
            if(target[i]>=nums[index]){
                target[i] = target[i] - nums[index];
                if(target[i] == 0 || dfs(nums,index-1,target))
                    return true;
                target[i] = target[i] + nums[index];
            }
        }
        return false;
    }
    
    
    public boolean canPartition(int[] nums) {
        int _sum = 0;
        for(int num:nums)
            _sum += num;
        if((_sum&1) == 1)
            return false;
        _sum = _sum>>1;
        Arrays.sort(nums);
        
        int[] target = {_sum,_sum};
        return dfs(nums,nums.length - 1,target);
    }
}

方法二 0 -1 背包

前面为初始判断,
后面部分为非常 典型的0-1背包问题。

扫描二维码关注公众号,回复: 5639835 查看本文章
class Solution {
    public boolean canPartition(int[] nums) {
        int tSum = 0;
        for(int num:nums)
            tSum += num;
        if((tSum&1) == 1)
            return false;
        tSum = tSum>>1;
        boolean[][] dp = new boolean[nums.length+1][tSum+1];
        dp[0][0] = true;
        for(int i = 1 ; i <=nums.length;i++)
            for(int j = 0 ;j <=  tSum;j++)
                if(j - nums[i-1] >= 0){
                    dp[i][j] = dp[i-1][j] | dp[i-1][j - nums[i-1]];
                }else{
                    dp[i][j] = dp[i-1][j];
                }
        return dp[nums.length][tSum];
    }
}

状态压缩

class Solution {
    public boolean canPartition(int[] nums) {
        int tSum = 0;
        for(int num:nums)
            tSum += num;
        if((tSum&1) == 1)
            return false;
        tSum = tSum>>1;
        boolean[] dp = new boolean[tSum+1];
        dp[0] = true;
        for(int num:nums)
            for(int j = tSum ;j >= num;j--)
                dp[j] |= dp[j - num];
        return dp[tSum];
    }
}

猜你喜欢

转载自blog.csdn.net/u013383813/article/details/88377677