这个题的问题其实可以改写为:从给定序列中选取一个数据之间不相邻的子序列,要求这个序列的和最大,输出这个最大的和。
动归的状态转移函数为:
f
(
n
)
=
m
a
x
(
f
(
n
−
1
)
,
f
(
n
−
2
)
+
n
u
m
s
[
n
]
)
f(n) = max(f(n-1), f(n-2)+nums[n])
f(n)=max(f(n−1),f(n−2)+nums[n])
其中:
- f ( n − 1 ) f(n-1) f(n−1)表示不选择当前数据,所以最大值和前n-1个数据对应的最大值相等
- f ( n − 2 ) + n u m s [ n ] f(n-2)+nums[n] f(n−2)+nums[n]表示选择当前数据,那么第n-1个数据肯定不能选,所以是前n-2个数据中的最大值加上当前值
如果考虑当前数据,只有以上两种情况,所以选择其中的最大值就是前n个数据中满足要求的子序列的和的最大值
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 如果输入0个元素
if len(nums) == 0:
return 0
# 如果输入1个元素
if len(nums) == 1:
return nums[0]
'''
当前最大的偷钱数:
f(n) = max(f(n-1), f(n-2)+nums[n])
'''
# 包含两个及两个以上的元素
dp = [0]*len(nums)
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i in range(2, len(nums)):
dp[i] = max(dp[i-1], dp[i-2]+nums[i])
return dp[-1]
solution = Solution()
print(solution.rob([1,2,3,1]))