LeetCode-698.划分为k个相等的子集、416.分割等和子集 回溯法

这里是两道题的题目描述:
LeetCode-698.划分为k个相等的子集
LeetCode-416.分割等和子集

LeetCode-698.划分为k个相等的子集

题解代码:

class Solution {
    public boolean canPartitionKSubsets(int[] nums, int k) {
        int sum=0;
        int maxValue=0;
        for(int i=0;i<nums.length;i++)
        {
            sum+=nums[i];
            maxValue=Math.max(maxValue,nums[i]);
        }
        if(sum%k!=0 || maxValue>sum/k)
        {
            return false;
        }
        int target=sum/k;
        return backTrace(nums,target,k,0,0,new boolean[nums.length]);
    }
    boolean backTrace(int[] nums,int target,int k,int curDiv,int start,boolean[] walked)
    {
        if(k==0) //已经给全的的集合分配了target
        {
            return true;
        }
        if(curDiv==target) //已经给当前集合分配了target
        {
            return backTrace(nums,target,k-1,0,0,walked); //为下一个集合分配
        }
        for(int i=start;i<nums.length;i++)
        {
            if(!walked[i] && curDiv+nums[i]<=target)
            {
                walked[i]=true;
                if(backTrace(nums,target,k,curDiv+nums[i],i+1,walked))
                {
                    return true;
                }
                walked[i]=false;
            }
        }
        return false;
    }
}

LeetCode-416.分割等和子集

方法1 由上一道题解变形而来 题解代码:

class Solution {
    public boolean canPartition(int[] nums) {
        if(nums.length<2)
        {
            return false;
        }
        int sum=0;
        int maxValue=0;
        for(int i=0;i<nums.length;i++)
        {
            sum+=nums[i];
            maxValue=Math.max(maxValue,nums[i]);
        }
        if(sum%2!=0 || maxValue>(sum/2))
        {
            return false;
        }
        Arrays.sort(nums); //对nums进行排序
        int target=sum/2;
        boolean[] walked=new boolean[nums.length]; //记录一个数字是否被分配
        return backTrack(nums,target,0,nums.length-1,walked);
    }
    boolean backTrack(int[] nums,int target,int curSum,int start,boolean[] walked)
    {
        if(curSum==target) //当前的子集被分配好,另外一个子集自然也被划分好
        {
            return true;
        }
        for(int i=start;i>=0;i--)
        {
            if(!walked[i] && curSum+nums[i]<=target)
            {
                walked[i]=true;
                if(backTrack(nums,target,curSum+nums[i],start-1,walked))
                {
                    return true;
                }
                walked[i]=false;
            }
        }
        return false;
    }
}

方法2 每个数字可选择在或不在一个子集中(若不在,则表示一定在另一个子集中),解空间是一个子集树
题解代码:

class Solution {
    public boolean canPartition(int[] nums) {
        if(nums.length<2)
        {
            return false;
        }
        int sum=0;
        int maxValue=0;
        for(int i=0;i<nums.length;i++)
        {
            sum+=nums[i];
            maxValue=Math.max(maxValue,nums[i]);
        }
        if(sum%2!=0 || maxValue>(sum/2))
        {
            return false;
        }
        int target=sum/2;
        return backTrack(nums,target,0,nums.length-1);
    }
    boolean backTrack(int[] nums,int target,int curSum,int start)
    {
        if(curSum==target) //当前的子集被分配好,另外一个子集自然也被划分好
        {
            return true;
        }
        for(int i=start;i>=0;i--)
        {
            if(curSum+nums[i]<=target)
            {
                if(backTrack(nums,target,curSum+nums[i],i-1))
                {
                    return true;
                }
            }
        }
        return false;
    }
}

你可能感兴趣的:(java,leetcode,dfs,算法)