美文网首页
2020-2-26 刷题记录

2020-2-26 刷题记录

作者: madao756 | 来源:发表于2020-02-26 23:37 被阅读0次

2 月份的刷题数量,比预期要少 15 道左右,dp 难度是挺大的,今天只做了三道,上半年目标是 450 道,加油

0X00 leetcode 刷题 3 道

  • leetcode 518. Coin Change 2
  • leetcode 474. Ones and Zeroes
  • leetcode 516. Longest Palindromic Subsequence

0X01 每道题的小小总结

518. Coin Change 2

class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        # 这是一个背包问题
        # 做法不能是 f(x) = f(x-1) + f(x-2) + f(x-5)
        # 这样会出现重复的问题
        # 而是
        # 用 1 可以有多少种解法
        # 用 1 和 2 可以有多少种解法
        # 用 1 和 2 和 5 可以有多少种解法
        
        dp = [0] * (amount + 1)
        # 当没有 amount 的时候可以用 0 个硬币的方法
        # 所以是 1
        dp[0] = 1

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

看看「官方题解」还是很不错的,做法就是

  • 用硬币 1 每个数字有几种解法
  • 用硬币 1 2 每个数字有几种解法
  • 用硬币 1 2 5 每个数字有几种解法
  • ....

474. Ones and Zeroes

这也是「背包问题」两个背包的问题

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        # 用动态规划做这个题
        # dp(i, j) 代表用 i 个 0 j 个 1 能组成多少个字符串
        # 所以写出 转移方程 dp(i, j) = max(dp(i-cost_zeros[k], j - cost_ones[k]) + 1, dp(i, j))
        # 每个字符串只能使用一次,我们遍历的时候要选择从后往前遍历,否则会重复计算当前字符串
        N = len(strs)
        dp, cost = [[0 for _ in range(n+1)] for _ in range(m+1)], [[0] * 2 for _ in range(N)]

        # 计算每个 str 用了多少个 0 和 1
        for i in range(N):
            cost[i][0] = strs[i].count("0")
            cost[i][1] = strs[i].count("1")
        
        for i in range(N):
            cost_zeros, cost_ones = cost[i][0], cost[i][1]
            for x in range(m, -1, -1):
                for y in range(n, -1, -1):
                    if cost_zeros <= x and cost_ones <= y:
                        dp[x][y] = max(dp[x - cost_zeros][y-cost_ones] + 1, dp[x][y])             
                        
        
        
        return dp[m][n]

有一个 trick 是:必须从后往前更新,否则会重复计算当前字符串

516. Longest Palindromic Subsequence

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        # 动态规划去做这个题目
        # 区间型动态规划
        # f(i, j) = max(f(i, j-1), f(i+1, j), f(i+1, j-1) + 2 | s[i] == s[j])
        # i,j 是下标
        # 按长度去做
        # 提交之前想想有没有漏掉的东西
        if len(s) == 0: return 0
        m = len(s)
        dp = [[0 for _ in range(m+1)] for _ in range(m)]
        
        # len 1
        for x in range(m):
            dp[x][x] = 1
        
        # len 2
        for x in range(m-1):
            dp[x][x+1] = 2 if s[x] == s[x+1] else 1
        
        for l in range(3, m+1):
            for x in range(m-l+1):
                y = x + l - 1
                dp[x][y] = max(dp[x+1][y], dp[x][y-1])
                if s[x] == s[y]:
                    dp[x][y] = max(dp[x][y], dp[x+1][y-1] + 2)
        
        return dp[0][m-1]

这个题有一个特别的地方,它是靠长度去遍历的「区间型」动态规划

相关文章

网友评论

      本文标题:2020-2-26 刷题记录

      本文链接:https://www.haomeiwen.com/subject/tglnchtx.html