leetcode : 337. House Robber III : 简单的树形DP

337. House Robber III

My Submissions
Total Accepted: 3244  Total Submissions: 8627  Difficulty: Medium

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

Example 1:

     3
    / \
   2   3
    \   \ 
     3   1
Maximum amount of money the thief can rob =  3 +  3 +  1 =  7.

Example 2:

     3
    / \
   4   5
  / \   \ 
 1   3   1
Maximum amount of money the thief can rob =  4 +  5 =  9.

通过读题可以发现:这是一个dp问题,如果将子问题设为,子树的max money。那么两种情况取最大值:1,root本身和root后第二层的节点maxmoney之和;2,root后第一层节点的maxmoney之和。

public int find(TreeNode x,HashMap<TreeNode, Integer> bag){
		if(x==null)
			return 0;
		if(bag.containsKey(x))
			return bag.get(x);
		else {
			int tt=search(x,bag);
			bag.put(x, tt);
			return tt;
		}
	}
	public int search(TreeNode root,HashMap<TreeNode, Integer> bag) {
		if(root==null)
			return 0;
		if(root.left==null&&root.right==null){
			return root.val;
		}else{
			int twol=find(root.left,bag);
			int twor=find(root.right,bag);
			int threell=root.left==null?0:find(root.left.left,bag);
			int threelr=root.left==null?0:find(root.left.right,bag);
			int threerl=root.right==null?0:find(root.right.left,bag);
			int threerr=root.right==null?0:find(root.right.right,bag);
			return Math.max(root.val+threell+threelr+threerl+threerr, 
					twol+twor);
		}	
	}
	public int rob(TreeNode root) {
		HashMap<TreeNode, Integer> bag=new HashMap<>();
		return search(root,bag);
	}

我的这种写法本来可以少一个函数,就是将hashmap设置成全局变量,但是那样的算法在java里面非常不容易维护的。因此使用hashmap作为参数,java中的参数都是引用,所以里面的值也是更改的。

还有一种更为巧妙地方法,时间复杂度没有变化,节省了hashmap的空间。这种能够方法每个节点设置了两个值,表示包含root节点的maxmoney和不包含的maxmoney,组后结果取两者最大值。

public int rob(TreeNode root) {
    int[] res = robSub(root);
    return Math.max(res[0], res[1]);
}

private int[] robSub(TreeNode root) {
    if (root == null) {
        return new int[2];
    }

    int[] left = robSub(root.left);
    int[] right = robSub(root.right);

    int[] res = new int[2];
    res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
    res[1] = root.val + left[0] + right[0];

    return res;
}






给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值