代码随想录训练营 打家劫舍

代码随想录训练营 dp

  • 198. 打家劫舍
    • code
  • 213. 打家劫舍 II
    • 分析
    • code
  • 337.打家劫舍 III

198. 打家劫舍

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

code

func rob(nums []int) int {
    n:=len(nums)
    dp :=make([]int,n+1)
    dp[0]  = 0
    dp[1] = nums[0]

    for i:=2;i<=n;i++{
        dp[i] = max(dp[i-1],dp[i-2]+nums[i-1])
    }
    return dp[n]
}
func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

213. 打家劫舍 II

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

分析

代码随想录训练营 打家劫舍_第1张图片

code


func rob(nums []int) int {
     if len(nums) == 1{
         return nums[0]
     }
     if len(nums) ==2{
         return max(nums[0],nums[1])
     }

     res1 := robRange(nums,0)
     res2 :=robRange(nums,1)
     return max(res1,res2)
}

func robRange(nums []int, start int) int{
    dp:=make([]int, len(nums))
    dp[1] = nums[start]
    for i:=2;i<len(nums);i++{
        dp[i] = max(dp[i-2] + nums[i-1 +start],  dp[i-1])
    }
    return dp[len(nums)-1]
}

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

337.打家劫舍 III

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。

func rob(root *TreeNode) int {
	res := robTree(root)
	return max(res[0], res[1])
}

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

func robTree(cur *TreeNode) []int {
	if cur == nil {
		return []int{0, 0}
	}
	// 后序遍历
	left := robTree(cur.Left)
	right := robTree(cur.Right)

    // 考虑去偷当前的屋子
	robCur := cur.Val + left[0] + right[0]
    // 考虑不去偷当前的屋子
	notRobCur := max(left[0], left[1]) + max(right[0], right[1])

    // 注意顺序:0:不偷,1:去偷
	return []int{notRobCur, robCur}
}

你可能感兴趣的:(算法,数据结构)