【LeetCode 简单题】51-打家劫舍

声明:

今天是第51道题。模拟小偷打劫沿街的房屋,每个房屋有非负的现金可取,但如果相邻打劫会触发报警,问如何不触发报警装置的情况下打劫到最大的金额。以下所有代码经过楼主验证都能在LeetCode上执行成功,代码也是借鉴别人的,在文末会附上参考的博客链接,如果侵犯了博主的相关权益,请联系我删除

(手动比心ღ( ´・ᴗ・` ))

正文

题目:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 1:

输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:

输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12 。

解法1。这是一个动态规划问题,无非就是满足前提的情况下当前遍历元素要不要加到金额当中(对应要不要打劫这一家),前提就是当前元素金额必须和前2个元素之前的相累加,那么就转化为比较大小的问题,用1个数组max_profit存放每一步的最优结果,比如说max_profit[2]存放的是遍历到第3个元素时,此时能打劫到的最大金额,落实代码中就是比较出当前nums[3]+max_profit[1]和max_profit[2]的大小,有以下几个要点:

  • 求全局最优的过程可以转化为求局部最优,也就是说求最大的打劫金额可以转化为求第1步、第2步、第3步的最优解,而这些最优解都是由前面求出的决定的,所以只要确认好边界条件就是成功的一半,第1步最大金额就是第1个值即nums[0],第2步最大金额是nums[0]和nums[1]的最大值,第3步的最大金额是max_profit[1]+nums[3]和max_profit[2]的最大值
  • 用1个数组存放每一步的最大金额

耗时28 ms, 在House Robber的Python提交中击败了58.61% 的用户,代码如下。

class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        max_profit = [0 for i in range(len_n)]    # 必须初始化,否则后面存放数据时无法通过index索引。为全0,元素个数和nums的一样
        len_n = len(nums)
        if len_n == 0:
            return 0
        if len_n == 1:
            return nums
        if len_n == 2:
            return max(nums)    # 原来nums只有2个元素时,可以直接传入整个nums,不必写成max(nums[0],nums[1])
        else:
            max_profit[0] = nums[0]
            max_profit[1] = nums[1]
            for i in range(2,len_n):
                max_profit[i] = max(max_profit[i-1], max_profit[i-2]+nums[i])
        return max_profit[-1] # 返回最后1个元素,即对应输入nums有n个元素时的最大金额

解法2。看下效率最高的解法,可能是环境的原因,我把结果粘贴过来执行结果耗时32ms,解法差不多,不过逻辑写得较简洁,可以注意一下,耗时20ms,代码如下。

 

class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
       
        if len(nums) == 0:
            return 0
        elif len(nums) < 2:
            return max(nums[0], nums[-1])
        money = [0]*len(nums)
        money[0],money[1] = nums[0], max(nums[0], nums[-1]
        for i in range(2,len(nums)-1):
            money[i] = max(money[i-2]+nums[i], money[i-1])
        return money[len(nums)-1]
            

结尾

解法1:https://blog.csdn.net/m0_37477175/article/details/80038517

解法2:LeetCode-提交成功后点击查看详情链接-可以看自己的用时排名和所有人提交的代码

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值