198.打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
思路: 动态规划,子问题每次查看当前值与跳一格值和与前一格值比较,每个位置保存当前及之前的最大值
class Solution:
def rob(self, nums: List[int]) -> int:
pre = cur = 0
for n in nums:
pre, cur = cur, max(pre + n, cur)
return cur
之前解法,相比最优解多记录了两个位置
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums:
return 0
if len(nums) <= 2:
return max(nums)
nums[2] += nums[0]
a,b,c,d = 0, nums[0], nums[1], nums[2]
for i in range(3, len(nums)):
a, b, c, d = b, c, d, max(b, c) + nums[i]
return max(c, d)
213.打家劫舍 II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
思路: 对于连成环的情况,第一个和最末一个必然不能同时被偷,所以问题拆分成 不偷第一个的最大值和不偷最后一个的最大值 取大
class Solution:
def rob(self, nums: [int]) -> int:
def my_rob(nums):
cur, pre = 0, 0
for num in nums:
cur, pre = max(pre + num, cur), cur
return cur
return max(my_rob(nums[:-1]),my_rob(nums[1:])) if len(nums) != 1 else nums[0]
打家劫舍 III
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
思路: 对于树结构,从底至上遍历,子结构为每个节点根据左右子节点保存的选择与不选择对应的值进行计算当前节点选择和不选择的值,
若选择当前节点,则当前值加上左右不选择的值
若不选择,则左右两边取最大值求和
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def rob(self, root: TreeNode) -> int:
def dfs(head):
if not head:
return (0, 0)
l = dfs(head.left)
r = dfs(head.right)
selected = head.val + l[1] + r[1]
notselected = max(l) + max(r)
return (selected, notselected)
ans = dfs(root)
return max(ans)
740. 删除并获得点数
给你一个整数数组 nums ,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。
思路:
把问题转换为打家劫舍,对于原数组,生成新的最大长度为max+1的数组,类似打家劫舍中相邻不能打劫,然后遍历nums 让all数组保存对应计数,最后求值位置变成计数乘以值,其他与打家劫舍相似
class Solution:
def deleteAndEarn(self, nums: List[int]) -> int:
m = max(nums)
all = [0 for _ in range(m + 1)]
pre, cur = 0, 0
for n in nums:
all[n] += 1
for i in range(len(all)):
pre, cur = cur, max(pre + all[i] * i, cur)
return cur

1704

被折叠的 条评论
为什么被折叠?



