力扣hot100 | 多维动态规划 | 62. 不同路径、64. 最小路径和、5. 最长回文子串、1143. 最长公共子序列、72. 编辑距离

62. 不同路径

力扣题目链接

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 "Start" )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 "Finish" )。

问总共有多少条不同的路径?

  • 【思路】
python 复制代码
# from functools import cache
from functools import lru_cache as cache # 3.9以下的版本

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        @cache
        def dfs(i, j): # 表示从(0,0)走到(i,j)的路径数
            if i < 0 or j < 0:  # 无法从(0,0)走到这些位置
                return 0
            if i == 0 and j == 0: # dfs(0, 0) 原地不动是一种办法
                return 1
            return dfs(i-1, j) + dfs(i, j-1)
        return dfs(m-1, n-1)
  • 时间复杂度 O(mn)
  • 空间复杂度 O(mn)

64. 最小路径和

力扣题目链接

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

参考自灵茶山艾府

python 复制代码
# from functools import cache
from functools import lru_cache as cache # 3.9以下的版本

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        @cache 
        def dfs(i: int, j: int) -> int:
            if i < 0 or j < 0:
                return inf
            if i == 0 and j == 0:
                return grid[i][j]
            return min(dfs(i, j - 1), dfs(i - 1, j)) + grid[i][j]
        return dfs(len(grid) - 1, len(grid[0]) - 1)
  • 时间复杂度 O(mn) ,其中 m 和 n 分别为 grid 的行数和列数。由于每个状态只会计算一次,动态规划的时间复杂度 = 状态个数 × 单个状态的计算时间。本题状态个数等于 O(mn),单个状态的计算时间为 O(1),所以总的时间复杂度为 O(mn)。
  • 空间复杂度 O(mn),保存多少状态,就需要多少空间。

5. 最长回文子串

力扣题目链接

给你一个字符串 s,找到 s 中最长的 回文 子串。

示例 1:

输入:s = "babad"

输出:"bab"

解释:"aba" 同样是符合题意的答案。
示例 2:

输入:s = "cbbd"

输出:"bb"

中心扩散法

参考自灵茶山艾府

写法一:奇偶分开判断

python 复制代码
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        ans_left = ans_right = 0

        # 奇回文串
        for i in range(n):
            l = r = i
            while l >= 0 and r < n and s[l] == s[r]:
                l -= 1
                r += 1
            # 循环结束后,s[l+1] 到 s[r-1] 是回文串
            if r - l - 1 > ans_right - ans_left:
                ans_left, ans_right = l + 1, r  # 左闭右开区间

        # 偶回文串
        for i in range(n - 1):
            l, r = i, i + 1
            while l >= 0 and r < n and s[l] == s[r]:
                l -= 1
                r += 1
            if r - l - 1 > ans_right - ans_left:
                ans_left, ans_right = l + 1, r  # 左闭右开区间

        return s[ans_left: ans_right]
  • 时间复杂度 O(n^2)
  • 空间复杂度 O(1)

1143. 最长公共子序列

力扣题目链接

给定两个字符串 text1text2,返回这两个字符串的最长公共子序列 的长度。如果不存在公共子序列 ,返回0

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例 1:

输入:text1 = "abcde", text2 = "ace"

输出:3

解释:最长公共子序列是 "ace" ,它的长度为 3 。
示例 2:

输入:text1 = "abc", text2 = "abc"

输出:3

解释:最长公共子序列是 "abc" ,它的长度为 3 。
示例 3:

输入:text1 = "abc", text2 = "def"

输出:0

解释:两个字符串没有公共子序列,返回 0 。

参考自灵茶山艾府

python 复制代码
# from functools import cache
from functools import lru_cache as cache # 3.9以下的版本

class Solution:
    def longestCommonSubsequence(self, s: str, t: str) -> int:
        n, m = len(s), len(t)
        @cache 
        def dfs(i: int, j: int) -> int: # s[:i+1]与t[:j+1]的最长公共子序列长度
            if i < 0 or j < 0:
                return 0
            if s[i] == t[j]:
                return dfs(i - 1, j - 1) + 1
            return max(dfs(i - 1, j), dfs(i, j - 1))
        return dfs(n - 1, m - 1)
  • 时间复杂度 O(nm)
  • 空间复杂度 O(nm)

72. 编辑距离

力扣题目链接

给你两个单词 word1word2, 请返回将 word1 转换成 word2 所使用的最少操作数

你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

示例 1:

输入:word1 = "horse", word2 = "ros"

输出:3

解释:

horse -> rorse (将 'h' 替换为 'r')

rorse -> rose (删除 'r')

rose -> ros (删除 'e')
示例 2:

输入:word1 = "intention", word2 = "execution"

输出:5

解释:

intention -> inention (删除 't')

inention -> enention (将 'i' 替换为 'e')

enention -> exention (将 'n' 替换为 'x')

exention -> exection (将 'n' 替换为 'c')

exection -> execution (插入 'u')

参考自灵茶山艾府

python 复制代码
# from functools import cache
from functools import lru_cache as cache # 3.9以下的版本

class Solution:
    def minDistance(self, s: str, t: str) -> int:
        n, m = len(s), len(t)
        @cache 
        def dfs(i: int, j: int) -> int: # 将word1[:i+1]转成word2[:j+1]的最少操作数
            if i < 0:
                return j + 1
            if j < 0:
                return i + 1
            if s[i] == t[j]:
                return dfs(i - 1, j - 1)
            return min(dfs(i - 1, j), dfs(i, j - 1), dfs(i - 1, j - 1)) + 1
        return dfs(n - 1, m - 1)
  • 时间复杂度 O(mn),其中 n 为 s 的长度,m 为 t 的长度。
  • 空间复杂度 O(mn)
相关推荐
lifallen3 小时前
Flink Watermark机制解析
大数据·算法·flink
IT古董3 小时前
【第五章:计算机视觉-项目实战之目标检测实战】1.目标检测算法理论-(6)一阶段目标检测算法YOLO系列思想详解:YOLOV1~YOLOV10
算法·目标检测·计算机视觉
小旺不正经3 小时前
数据库表实现账号池管理
数据库·后端·算法
豆芽8193 小时前
模糊控制Fuzzy Control
人工智能·算法·模糊控制
静水流深-刘申4 小时前
算法继续刷起-2025年09月26日
开发语言·c++·算法
木头左4 小时前
跨周期共振效应在ETF网格参数适配中的应用技巧
开发语言·python·算法
顾你&5 小时前
机器学习之无监督学习算法大总结
学习·算法·机器学习
神龙斗士2406 小时前
Java 数组的定义与使用
java·开发语言·数据结构·算法
Y.O.U..6 小时前
力扣HOT100-跳跃游戏II
算法·leetcode