打家劫舍问题大击破
问题一、
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
解法:核心在于 nums[i] = max(nums[i]+nums[i-2],nums[i-1])
func rob(nums []int) int { if len(nums)==0{ return 0 } if len(nums)>=2{ nums[1] = max(nums[0],nums[1]) } for i:=2;i<len(nums);i++{ nums[i] = max(nums[i]+nums[i-2],nums[i-1]) } return nums[len(nums)-1] } func max(a,b int)int{ if a>b{ return a } return b }
问题二:
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。
// 抢第一家,不能抢最后一家 func rob(nums []int) int { ln := len(nums) if ln==0{ return 0 } if ln == 1{ return nums[0] } dp1, dp2 := make([]int,ln),make([]int,ln) dp1[0] = nums[0] dp2[0] = 0 dp1[1] = max(nums[0],nums[1]) dp2[1] = nums[1] for i:=2;i<ln;i++{ dp1[i] = max(dp1[i-2]+nums[i],dp1[i-1]) dp2[i] = max(dp2[i-2]+nums[i],dp2[i-1]) } return max(dp1[ln-2],dp2[ln-1]) } func max(a,b int)int{ if a>b{ return a } return b }
问题三:
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ func max(a,b int)int{ if a>b{ return a } return b } func rob(root *TreeNode) int { var roob func(root *TreeNode)(int,int) roob = func(root *TreeNode)(int,int){ if root ==nil{ return 0, 0 } left,left_safe := roob(root.Left) right,right_safe := roob(root.Right) return root.Val+ left_safe+right_safe,max(left,left_safe)+max(right,right_safe) } rv,rv_safe := roob(root) return max(rv,rv_safe) }