【动态规划:打家劫舍系列问题详解】


前言

提示:打家劫舍问题是个很经典的动态规划问题,类似的还有背包问题、凑零钱问题等等

这类问题大部分都是择优选择,如: res = max(选择打劫,选择不打劫)
在这里插入图片描述


一、动态规划 LeetCode. 198. 打家劫舍问题描述

打家劫舍问题

二、动态规划 LeetCode. 198. 打家劫舍问题解法

核心代码: res = max(打劫, 不打劫)

核心代码: res = max(打劫, 不打劫)

核心代码: res = max(打劫, 不打劫)

func rob(nums []int) int {
    // 1, 方法1
    return rob1(nums)
    // 2, 方法2
    // return rob2(nums)
}


func rob1(nums []int) int {
    n := len(nums)
    // 1, baseCase
    if n ==0 {
        return 0
    }
    if n == 1{
        return nums[0]
    }
    var (
        s = make([]int, n+1)
    )
    s[0] = 0
    s[1] = nums[0]
    for i:=1; i<n; i++{
    	// 核心代码一行:做选择 = max(选择打劫的结果, 不选择打劫的结果)
        s[i+1] = getMax(s[i], s[i-1]+nums[i])
    }
    return s[n]
}

func rob2(nums []int) int {
    n := len(nums)
    // 1, baseCase
    if n ==0 {
        return 0
    }
    if n == 1{
        return nums[0]
    }
    // 2, 状态
    // 用s0,s1,s2可以优化空间,这点跟`斐波那契数列`的优化一样,因为不需要记住全部的状态,只需要用3个变量表示中间状态
    var s0 = 0
    var s1 = nums[0]
    var s2 = 0
    for i:=1; i<n; i++{
        // 做选择,sel = max(打劫, 不打劫)
        s2 = getMax(s1, s0 + nums[i])
        s0 = s1
        s1 = s2
    }
    return s2
}

func getMax(a,b int)int{
    if a>b{
        return a
    }
    return b
}

打家劫舍时空开销

三、动态规划 LeetCode 213. 打家劫舍 II

一行代码搞定打家劫舍问题
核心思想:将圈圈拆开,拆成2个LeetCode.198 打家劫舍问题

func rob(nums []int) int {
    n := len(nums)
    if n==0{
        return 0
    }else if n==1{
        return nums[0]
    }
    // 打劫第一次,打劫第二次
    return getMax( robHelp(nums[0:n-1]), robHelp(nums[1:n]) )

}

func robHelp(nums []int) int{
    n := len(nums)
    if n==0{
        return 0
    }else if n==1{
        return nums[0]
    }
    var (
        s0 = 0
        s1 = nums[0]
        s2 = 0
    )
   
    for i:=1; i<n; i++{
        // 核心代码 res = max(打劫,不打劫)
        s2 = getMax(s1, s0 + nums[i])
        s0 = s1
        s1 = s2
    }
    return s2
}

func getMax(a,b int) int {
    if a>b{
        return a
    }
    return b
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值