213. 打家劫舍 II

该博客讨论了一种动态规划问题,涉及在环形数组中选择连续子序列以最大化盗窃价值。作者提出了三个不同版本的解决方案,从初始的O(n^2)时间复杂度优化到O(n),最后进一步减少空间复杂度。每个版本都详细解释了思路,并提供了Python实现。优化后的算法避免了重复计算,提高了效率。
摘要由CSDN通过智能技术生成
总结:
	简简单单动态规划,和字符串一样,看以当前元素结尾所能取到的最大值
	没什么好说的,注意是一个圈所以第一个元素和最后一个元素不共存,所以可以
	分为两种情况,有一无后,有后无一
'''
    注意:
        房屋被围成了一圈,所以第一个和最后一个一定不会同时出现
        假设出现第一个不出现最后一个
            dp[i]=nums[i-1]+dp[i-1] i=1,2,3,4...
            dp[i]表示长度为i  nums[i-1]表示下标为i-1
            dp[0]=0

        对于
'''

def fun1(nums):
    if len(nums)<=3: #只能偷一个
        return max(nums)
    dp=[0]*(len(nums)+1)
    max_1=0
    dp[1]=nums[0]
    dp[2]=nums[1]
    for i in range(3,len(nums)):#从1到len(s)-2
        dp[i]=nums[i-1]+max(dp[0:i-1:])#找到可取范围内的最大值
        if max_1<dp[i]:
            max_1=dp[i]

    dp=[0]*(len(nums)+1)
    max_2=0
    dp[1]=nums[-1]
    dp[2]=nums[-2]
    for i in range(3,len(nums)):
        dp[i]=nums[-i]+max(dp[0:i-1:])
        if max_2<dp[i]:
            max_2=dp[i]

    return max(max_2,max_1)
def fun2(nums):
    '''
        上面代码是可以化简的,我每次使用的都是与i相隔一格的集合最大值
        所以可以拿变量记录最大值,这样的话可以省去每次查找花费的时间

    :param nums:
    :return:
    '''
    if len(nums)<=3: #只能偷一个
        return max(nums)
    dp=[0]*(len(nums)+1)
    max_1=0
    dp[1]=nums[0]
    dp[2]=nums[1]
    pre1=dp[1]
    for i in range(3,len(nums)):#从1到len(s)-2
        dp[i]=nums[i-1]+pre1#找到可取范围内的最大值
        if max_1<dp[i]:
            max_1=dp[i]
        if pre1<dp[i-1]:
            pre1=dp[i-1]
    print(max_1)
    dp=[0]*(len(nums)+1)
    max_2=0
    dp[1]=nums[-1]
    dp[2]=nums[-2]
    pre2=dp[1]
    for i in range(3,len(nums)):
        dp[i]=nums[-i]+pre2
        if max_2<dp[i]:
            max_2=dp[i]
        if pre2<dp[i-1]:
            pre2=dp[i-1]
    return max(max_2,max_1)
print(fun2([2,3,2,1,2,3,4,5,6,7,1,1,1]))
def fun3(nums):
    '''
        fun1是一个时间复杂度为o(n**2) 空间复杂度为o(n)的算法
        fun2优化了时间复杂度变为o(n),采用变量记录,少了重复操作,空间复杂度没变
        现在在fun2的基础上优化空间复杂度
    :param nums:
    :return:
    '''
    if len(nums)<=3: #只能偷一个
        return max(nums)
    max_1=max(nums[0],nums[1])
    pre1=nums[0]
    pre2=nums[1]
    for i in range(3,len(nums)):#从1到len(s)-2
        cur=nums[i-1]+pre1
        if max_1<cur:
            max_1=cur
        if pre1<pre2:
            pre1=pre2
        pre2=cur

    max_2=max(nums[-1],nums[-2])
    pre1=nums[-1]
    pre2=nums[-2]
    for i in range(3,len(nums)):
        cur=nums[-i]+pre1
        if max_2 < cur:
            max_2 = cur
        if pre1<pre2:
            pre1=pre2
        pre2=cur
    return max(max_2,max_1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值