动态规划

  • 确定基础情况 base case
  • 最优子结构
  • 状态转移方程

70. 爬楼梯open in new window

70. 爬楼梯
class Solution(object):
    def climbStairs(self, n):
        f1 = 1
        f2 = 2
        if n == 1:
            return f1
        if n == 2:
            return f2
        for _ in range(3, n + 1):
            fn = f2 + f1
            f1 = f2
            f2 = fn
        return fn

    def climbStairs(self, n):
        dp = [0] * (n + 1)
        dp[0] = 1
        dp[1] = 1
        for i in range(2, n + 1):
            dp[i] = dp[i - 1] + dp[i - 2]
        return dp[n]

121. 买卖股票的最佳时机open in new window

121. 买卖股票的最佳时机
class Solution:
    # 暴力循环 两次遍历
    def maxProfit(self, prices) -> int:
        res = 0
        for i in range(len(prices)):
            for j in range(i + 1, len(prices)):
                res = max(res, prices[j] - prices[i])
        return res

    # 一次遍历,记录最低点
    def maxProfit2(self, prices) -> int:
        res = 0
        low = float("inf")
        for i in range(len(prices)):
            low = min(low, prices[i])  # 取最左最小价格
            res = max(res, prices[i] - low)  # 直接取最大区间利润
        return res

198. 打家劫舍open in new window

198. 打家劫舍
# 当前偷不偷,取决于前一个房屋和前两个房屋是否被偷了

class Solution:
    def rob(self, nums) -> int:
        if len(nums) == 0:
            return 0
        if len(nums) == 1:
            return nums[0]
        dp = [0] * len(nums)
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])

        for i in range(2, len(nums)):
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
        return dp[-1]

    def rob2(self, nums):
        return self.dp(self, nums, 0)

    def dp(self, nums, start):
        if start >= len(nums):
            return 0
        # self.dp(nums, start + 1) 不抢,去下一家
        # self.dp(nums, start + 2) + nums[start] 抢,去下下家
        res = max(self.dp(nums, start + 1), self.dp(nums, start + 2) + nums[start])
        return res

213. 打家劫舍 IIopen in new window

213. 打家劫舍 II
# 这个和基础的打家劫舍的区别在于,首尾相连了

# 情形一:不包含首尾元素
# 情形二:包含首,不包含尾
# 情形三:不包含首,包含尾

class Solution:
    def rob(self, nums) -> int:
        if len(nums) == 1:
            return nums[0]
        first = self.rob_range(nums[1:])  # 不抢第一家
        last = self.rob_range(nums[:-1])  # 不抢最后一家
        return max(first, last)

    def rob_range(self, nums):
        dp = [0] * len(nums)
        dp[0] = nums[0]
        for i in range(1, len(nums)):
            if i == 1:
                dp[i] = max(dp[i - 1], nums[i])
            else:
                dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
        return dp[-1]

322. 零钱兑换open in new window

322. 零钱兑换
class Solution:
    def coinChange(self, coins, amount: int) -> int:
        dp = [amount + 1] * (amount + 1)
        dp[0] = 0

        for coin in coins:
            for x in range(coin, amount + 1):
                dp[x] = min(dp[x], dp[x - coin] + 1)

        return -1 if dp[amount] == amount + 1 else dp[amount]

337. 打家劫舍 IIIopen in new window

337. 打家劫舍 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:
        if not root:
            return 0
        if not root.left and not root.right:
            return root.val
        # 抢父节点
        val_1 = root.val
        if root.left:
            val_1 += self.rob(root.left.left) + self.rob(root.left.right)
        if root.right:
            val_1 += self.rob(root.right.left) + self.rob(root.right.right)
        # 不抢父节点
        val_2 = self.rob(root.left) + self.rob(root.right)
        return max(val_1, val_2)

    def rob2(self, root: TreeNode):
        dp = self.traversal(root)
        return max(dp)

    def traversal(self, root: TreeNode):
        # 空节点,不偷
        if not root:
            return (0, 0)
        left = self.traversal(root.left)
        right = self.traversal(root.right)
        # 不偷当前节点, 偷子节点
        val_1 = max(left[0], left[1]) + max(right[0], right[1])
        # 偷当前节点, 不偷子节点
        val_2 = root.val + left[0] + right[0]
        return (val_1, val_2)

509. 斐波那契数open in new window

509. 斐波那契数
class Solution:
    def fib(self, n: int) -> int:
        if n == 1 or n == 2:
            return 1
        return self.fib(n - 1) + self.fib(n - 2)

    def fib2(self, n):
        arr = [0] * (n + 1)
        return self.hepler(arr, n)

    def hepler(self, arr, n):
        if n == 0 or n == 1:
            return n
        if arr[n] != 0:
            return arr[n]
        arr[n] = self.hepler(arr, n - 1) + self.hepler(arr, n - 2)
        return arr[n]

    def fib3(self, n: int) -> int:
        if n == 0:
            return 0
        dp = [0] * (n + 1)
        dp[0] = 0
        dp[1] = 1
        for i in range(2, n + 1):
            dp[i] = dp[i - 1] + dp[i - 2]
        return dp[n]

746. 使用最小花费爬楼梯open in new window

746. 使用最小花费爬楼梯
class Solution:
    def minCostClimbingStairs(self, cost):
        dp = [0] * len(cost)
        dp[0] = cost[0]
        dp[1] = cost[1]
        for i in range(2, len(cost)):
            dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
        return min(dp[len(cost) - 1], dp[len(cost) - 2])

146. LRU 缓存open in new window

146. LRU 缓存
class ListNode:
    def __init__(self, key=0, val=0):
        self.key = key
        self.val = val
        self.prev = None
        self.next = None


class LRUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.size = 0
        self.hashmap = {}
        self.head = ListNode()
        self.tail = ListNode()
        self.head.next = self.tail
        self.tail.prev = self.head

    def remove_node(self, node: ListNode):
        node.prev.next = node.next
        node.next.prev = node.prev

    def add_to_head(self, node: ListNode):
        node.prev = self.head
        node.next = self.head.next
        self.head.next.prev = node
        self.head.next = node

    def move_to_head(self, node: ListNode):
        self.remove_node(node)
        self.add_to_head(node)

    def remove_tail(self):
        node = self.tail.prev
        self.remove_node(node)
        return node

    def get(self, key: int) -> int:
        if key not in self.hashmap:
            return -1

        node = self.hashmap[key]
        self.move_to_head(node=node)
        return node.val

    def put(self, key: int, value: int) -> None:
        if key not in self.hashmap:
            node = ListNode(key, value)
            self.hashmap[key] = node
            self.add_to_head(node)
            self.size += 1
            if self.size > self.capacity:
                removed = self.remove_tail()
                self.hashmap.pop(removed.key)
                self.size -= 1
        else:
            node = self.hashmap[key]
            node.val = value
            self.move_to_head(node)


# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
上次更新:
贡献者: kongzZ