LeetCode 416、606题解(中等dp、回溯)

class Solution {
    public boolean canPartition(int[] nums) {
        int n = nums.length;
        /*计算总和*/
        int targetSum = 0;
        int maxNum = 0;
        for(int num:nums){
            targetSum+=num;
            maxNum = Math.max(maxNum,num);
        }
        if(targetSum%2!=0){
            return false;
        }
        int target = targetSum/2;
        /*[1,2,3,8]*/
        if(maxNum>target){
            return false;
        }
        boolean[] dp = new boolean[target+1];
        Arrays.fill(dp,false);
        dp[0] = true;

        for(int i=0;i<n;i++){
            int num = nums[i];
            for(int j=target;j>=num;j--){
                dp[j] |= dp[j-num];
            }
        }

        return dp[target];
    }
}

看示例来理解dp的构造

root=[1,5,11,5]

new dp[11+1]
Arrays.fill(dp,false);
dp[0] = true;

进行第三轮的循环后 解释一下
dp = [true, true, false, false, false, true, true, false, false, false, true, true]

假设我们正在解决一个分割等和子集问题,数组 nums = {1, 5, 11, 5},并且我们已经计算了目标值 target = sum / 2 = 11。这个 dp 数组就是在尝试从数组 nums 中选择子集,使得它们的和达到 target = 11 时的结果。

dp[0] = true:和为 0 的子集是空集,总是成立。
dp[1] = true:表示我们可以选择元素 1 来得到和为 1 的子集。
dp[2] = false:表示不能通过任何子集的元素组合得到和为 2
dp[3] = false:表示不能通过任何子集的元素组合得到和为 3
dp[4] = false:表示不能通过任何子集的元素组合得到和为 4
dp[5] = true:表示我们可以通过选择元素 5 得到和为 5 的子集(例如 {5})。
dp[6] = true:表示我们可以通过选择元素 15 得到和为 6 的子集(例如 {1, 5})。
dp[7] = false:表示不能通过任何子集的元素组合得到和为 7
dp[8] = false:表示不能通过任何子集的元素组合得到和为 8
dp[9] = false:表示不能通过任何子集的元素组合得到和为 9
dp[10] = true:表示我们可以通过选择元素 55 得到和为 10 的子集(例如 {5, 5})。
dp[11] = true:表示我们可以通过选择元素 155 得到和为 11 的子集(例如 {1, 5, 5})。

回溯

当回溯到子叶时,子叶的root.left.val等于root.right.val直接返回s,如果是节点,就根据节点的子叶的两种情况进行回溯

if(l.isEmpty()) return s+"()"+"("+r+")";
if(r.isEmpty()) return s+"("+l+")";
class Solution{
	public String tree2str(TreeNode root){
		if(root==null) return '';
		String s = String.valueOf(root.val);
		String l = tree2str(root.left);
		String r = tree2str(root.right);
		if(l.isEmpty()||r.isEmpty()){
			if(l==r) return s;
			if(l.isEmpty()) return s+"()"+"("+r+")";
			if(r.isEmpty()) return s+"("+l+")";
		}
		return s+"("+l+")"+"("+r+")";
	}
}

当情况如下所示则会调用该return值

return s+"("+l+")"+"("+r+")";

可以使用StringBuilder去代替String使得速度快一些

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值