LeetCode 337. House Robber III

               大概题意:给定一棵二叉树,每个节点都有一个值,要求从其中选取若干个节点,是的值的和最大,约束条件为任意两个选取的节点之间不能相连。

          解题的思路也很清晰,我们可以用动态规划的做法,以递归的方法实现。对于任意一个父节点,我们有取与不取两种选择:如果取,则其两个子节点都不能取;如果不取,则其两个子节点即可取也可以不取。

          一开始我实现了一个函数来辅助实现。函数为 int max_rob(TreeNode* root, int t) ,其中参数t 用来表示当前节点是否取:1为取,0为不取。具体实现如下:

class Solution {
public:
	int max_rob(TreeNode* root, int t) {
		if (root == NULL) return 0 ;
		int mrl0 = max_rob(root->left, 0) ;
		int mrr0 = max_rob(root->right, 0) ;
		if (t == 1) return root->val + mrl0 + mrr0 ;
		else {
			return max(max_rob(root->left, 1), mrl0) + max(max_rob(root->right, 1), mrr0 )) ;
		}
	}
    int rob(TreeNode* root) {
        return max(max_rob(root, 1), max_rob(root, 0) ) ;
    }
};
          然而这样的写法是TLE的,不能通过最后一个测试样例。观察写法,虽然已经用了两个局部变量mrl0 和 mrr0 来记录两个子节点不取的情况下的各自的最大值了,但在最差的情况下,即t = 1 的情况下,每个节点都要对其两个子节点遍历两次,相当于遍历4个节点。如果树的层数为n,则时间复杂度就为O(4^(n+1))。

          所以我们需要更高效的实现。能不能再遍历每个节点的时候就把取了它和不取它的最大值都求出来呢?是可以的。具体实现如下:

class Solution {
public:
	pair<int, int> max_rob(TreeNode* root) {
		if (root == NULL) return 0 ;
		
		pair<int, int> lans = max_rob(root -> left) ;
		pair<int, int> rans = max_rob(root -> right) ;
		
		pair<int, int> ans ;
		ans.first = root->val + lans.second + rans.second ;
		ans.second = max(lans.first, lans.second) + max(rans.first, rans.second) ;
		
		return ans ;
          
	}
    int rob(TreeNode* root) {
        pair<int, int> ans = max_rob(root) ;
        return max(ans.first, ans.second) ;
    }
};

       这种写法,每个节点只需遍历其两个子节点各一次,如果树的层数为n,则时间复杂度为O(2^(n+1)),这种实现方法的时间复杂度远远小于上一种写法。

       这道题对我的启发与其说是算法上,不如说是在写法上。不同的写法可能会出现差异很大的时间复杂度。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值