zoukankan      html  css  js  c++  java
  • 力扣516题、72题、1312题(最长回文子序列,编辑距离,构造回文串)

    516、最长回文子序列

    基本思想:

    动态规划运用二维dp数组

    具体实现:

    1、确定状态:

    (1)最后一步----字符串s[i:j]中的最长回文子序列的长度

    (2)子问题

     2、转移方程

    (1)s[i]==s[j]

    把字符串左右同时缩小一下+2,上图情况1 +2

    (2)s[i]!=s[j]

    不相等的话说明这两个字符不可能同时出现在s[i:j]的最长回文子序列

    选择上图情况2和3较大的一个

    3、初始状态

    dp[i][i] = 1

    i比j大的地方dp都是0

    因为i永远在j的前面

    4、计算顺序

    从左到右  知道j,要先知道 j-1

    从下到上  知道i,要先知道 i+1

     

     代码:

    class Solution:
        def longestPalindromeSubseq(self, s: str) -> int:
            n = len(s)
            dp=[[0]*n for i in range(n)]
            for i in range(n):
                dp[i][i] = 1
            for i in range(n-2,-1,-1):
                for j in range(i+1,n):
                    if s[i] == s[j]:
                        dp[i][j] = dp[i+1][j-1] +2
                    else:
                        dp[i][j] = max(dp[i+1][j],dp[i][j-1])
            return dp[0][n-1]

    72、编辑距离

     基本思想:

    动态规划,二维数组

    具体实现:

    1、确定状态:

    (1)最后一步--dp[i][j]表示s1[0.....i-1]和s2[0......j-1]的编辑距离

    (2)子问题

    i索引对应的是需要改变的

    插入--在i的后面插入j对应的字符,插入完以后j往前一步, i不动

    删除--删除i对应的字符,删除完以后i往前一步,j不动

    替换--把i对应的字符替换成j对应的字符,替换完都往前走一步

    跳过--说明i和j对应的字符相同,dp[i][j] == dp[i-1][j-1]

    2、状态转移方程:

    (1)word1[i] == word[j]

    dp[i][j] == dp[i-1][j-1]

    (2)word1[i] != word[j]

    dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1

    3、初始状态:

     horse是word1,ros是word2

    第一行,word1为空,word1变成word2的最少步数就是插入操作

    第一列,Word2为空,word1变成word2的最少步数就是删除操作

    4、计算顺序:

    从左到右,从上到下

    代码:

    class Solution:
        def minDistance(self, word1: str, word2: str) -> int:
            m = len(word1)
            n = len(word2)
            dp = [[0 for _ in range(n+1)]for _ in range(m+1)]
            for i in range(1,m+1):
                dp[i][0] = i
            for j in range(1,n+1):
                dp[0][j] = j
            for i in range(1,m+1):
                for j in range(1,n+1):
                    if word1[i-1] == word2[j-1]:
                        dp[i][j] = dp[i-1][j-1]
                    else:
                        dp[i][j] = 1+min(dp[i-1][j],dp[i-1][j-1],dp[i][j-1])
            return dp[m][n]

    1312、以最小插入次数构造回文串

    基本思想:

    动态规划

    具体实现:

    1、确定状态:

    最后一步---dp[i][j]表示构成的回文串的插入最少的次数

    子问题---dp[i][j-1],dp[i+1][j],dp[i+1][j-1]构成回文串的插入最少的次数

    2、状态转移方程:

    (1)s[i] == s[j]

    不需要任何插入,只要看s[i+1....j-1]是否是回文串就行了

    dp[i][j] = dp[i+1][j-1] 

    (2)s[i] != s[j]

    dp[i+1][j] ,dp[i][j-1] 其中次数少的一种至少插入一个字符

    3、初始状态:

    i == j时,dp[i][j]=0

    4、计算顺序

    从左到右,从下到上

    代码:

    class Solution:
        def minInsertions(self, s: str) -> int:
            n = len(s)
            dp = [[0]*n for _ in range(n)]
            for i in range(n-2,-1,-1):
                for j in range(i+1,n):
                    if s[i] == s[j]:
                        dp[i][j] = dp[i+1][j-1]
                    else:
                        dp[i][j] = 1 + min(dp[i+1][j], dp[i][j-1])
            return dp[0][n-1]

    空间复杂度降低

    class Solution:
        def minInsertions(self, s: str) -> int:
            n = len(s)
            dp = [0]*n 
            for i in range(n-2,-1,-1):
                pre = 0
                for j in range(i+1,n):
                    temp = dp[j]
                    if s[i] == s[j]:
                        dp[j] = pre
                    else:
                        dp[j] = 1 + min(dp[j], dp[j-1])
                    pre = temp
            return dp[n-1]
  • 相关阅读:
    【转】 VC MFC 钩子 实现 自绘 窗体 标题栏 非客户区
    Scintilla开源库使用指南(二)
    Scintilla开源库使用指南(一)
    【转】MFC 多文档
    多视图识别
    获得MFC窗口其它类指针的方法
    sql2005 查看数据库或表大小的系统存储过程 sp_spaceused
    哪里是乐土?关于团队良性循环 (转)
    项目管理反思——前言
    项目经理思考——团队
  • 原文地址:https://www.cnblogs.com/zhaojiayu/p/14532590.html
Copyright © 2011-2022 走看看