leetcode动态规划专练

House Robber

题面:给定非负整数数组A[n],从中选出若干个元素,要求所选元素不能相邻,求所选元素之和的最大值。

思路:假设已经知道对于A[i]的答案,为f[i],要推出A[i+1]的答案,对于第i+1个元素,如果选,那么第i个元素就不能选,f[i+1] = a[i+1] + f[i-1];如果不选,那么有f[i+1] = f[i],从而f[i+1] = max(f[i], a[i+1] + f[i-1]),因递推式中每一项只与前两项有关,可将空间优化到O(1)。

def rob(self, nums):
    last, now = 0, 0
    for i in nums:
        last, now = now, max(now, last + i)
    return now

House Robber II

题面:非负整数数组A[n]构成一个环,从中选若干个元素,要求所选元素不能相邻,求所选元素之和的最大值。

思路:根据是否选择a[n]分成两种情况,转化为不带环的情况。

def rob1(self, nums):
    last, now = 0, 0
    for i in nums:
        last, now = now, max(now, last + i)
    return now
def rob(self, nums):
    if len(nums) == 0: return 0
    return max(self.rob1(nums[:-1]), nums[-1] + self.rob1(nums[1:-2]))

House Robber III

题面:在二叉树上的每个节点上有非负整数值,现要从树上选出若干个节点,要求所选节点不能是相邻的父子节点,求所选节点值之和的最大值。

思路:自上而下直接递归可得到正确结果,但因为做了大量重复计算,效率太低,宜改成自下而上的递推做法。对于某个节点,先计算其左右子节点的结果,包括选择和不选择两种情况分别可得到的最大结果,然后考虑根节点本身,也分选择和不选择两种情况。

def rob1(self, root):
    if not root: return (0, 0)
    left = self.rob1(root.left)
    right = self.rob1(root.right)
    return (root.val + left[1] + right[1], max(left) + max(right))
def rob(self, root):
    return max(self.rob1(root))
Table of Contents