LeetCode 416分割等和子集

LeetCode 416分割等和子集_第1张图片

本题其实就是选取一个子集,使子集的和等于数组和的一半 若能得到此子集,则存在.

此题属于01背包问题

首先计算数组中所有元素的和,若和为奇数,则直接返回false即可

创建boolean型的dp[ i ][ j ]数组, 这个数组的含义就是是否存在从前 i 个数组元素中选取某些元素使得元素和等于 j

状态转移方程

dp[i][j]=dp[i-1][j]||dp[i-1][j-nums[i]];

dp[i-1][j] : 意思是不选择当前元素的情况下 已经可以满足使得元素和为 j

dp[i-1][j-nums[i]] :意思是选择当前元素后恰好也可使得元素和为 j

题解如下:

class Solution {
    public boolean canPartition(int[] nums) {
         if(nums.length==0) return false;
         int sum=0;
         for(int i:nums){
            sum+=i;
         }
         if(sum%2!=0) return false;     //如果和为奇数
        boolean[][] dp=new boolean[nums.length][sum/2+1];
        dp[0][0]=true;
       if (nums[0] <= sum/2) {      //如果数组第一个元素在范围内
            dp[0][nums[0]] = true;
        }
       for(int i=1;i=nums[i])
               dp[i][j]=dp[i-1][j]||dp[i-1][j-nums[i]];
               else{
                  dp[i][j]=dp[i-1][j];    
               }
           }
       }
       return dp[nums.length-1][sum/2];
    }
}

对dp数组进行一维优化:(第二层循环要倒序)

class Solution {
    public boolean canPartition(int[] nums) {
         if(nums.length==0) return false;
         int sum=0;
         for(int i:nums){
            sum+=i;
         }
         if(sum%2!=0) return false;     //如果和为奇数
         boolean[] p=new boolean[sum/2+1];      //定义背包数组
         p[0]=true;
         for(int i=0;i=nums[i];j--){    //更新数组 
                 p[j]=p[j]||p[j-nums[i]];
             }
         }
         return p[sum/2];
    }
}

你可能感兴趣的:(leetcode,算法,职场和发展)