经典题目(1):编辑距离 斐波那契数列

题目一

给定两个字符串 str1 和 str2 ,请你算出将 str1 转为 str2 的最少操作数。

你可以对字符串进行3种操作:

1.插入一个字符

2.删除一个字符

3.修改一个字符。

字符串长度满足 1≤n≤1000 1≤n≤1000  ,保证字符串中只出现小写英文字母。


方法

(1)在word1末尾插入word2末尾的字,然后把两个词最后一个字母抵消

比较word1[0..i]和word2[0..j-1]的结果

(2)在word1末尾删除一个字母(e),比较word1[0..i-1]和word2[0..j]的结果

(3)将word1的最后一个字母替换成word2的最后一个字母,然后同时删除最后一个字母,比较word1[0..i-1]和word2[0..j-1]的结果

这里要用到动态规划,然后根据上述步骤抽取出状态转移方程

要注意的是,尽管题目中说str1和str2都不是空字符串,在构建状态转移方程时仍然要考虑str为0的情况,因为在推导第一个字符的时候,要和空字符的情况进行比较

代码

class Solution:
    def editDistance(self , str1: str, str2: str) -> int:
        # write code here
        m=len(str1)
        n=len(str2)
        dp=[[0]*(m+1) for _ in range(n+1)] #n2行,m1列
        # 仍然需要有空字符串情况,因为计算第一个字符时要使用
        for i in range(m+1):
            dp[0][i]=i
        for i in range(n+1):
            dp[i][0]=i
        # 由于有了空字符串,所以初始化的时候直接可以用i
        for i in range(1,m+1):
            for j in range(1,n+1):
                if str1[i-1]==str2[j-1]:
                    # 由于有空字符串,比较字符串是否相等时要减一
                    dp[j][i]=dp[j-1][i-1]
                else:
                    dp[j][i]=min(dp[j-1][i-1],dp[j-1][i],dp[j][i-1])+1
        return dp[n][m]

题目一变体

给定两个字符串str1和str2,再给定三个整数ic,dc和rc,分别代表插入、删除和替换一个字符的代价,请输出将str1编辑成str2的最小代价。

数据范围:0≤∣str1∣,∣str2∣≤50000≤∣str1∣,∣str2∣≤5000,0≤ic,dc,rc≤10000 0≤ic,dc,rc≤10000 

要求:空间复杂度 O(n),时间复杂度 O(nlogn)

方法

和上题的思路类似,区别是区分三种情况加入代价

代码

class Solution:
    def minEditCost(self , str1: str, str2: str, ic: int, dc: int, rc: int) -> int:
        # write code here
        m=len(str1)
        n=len(str2)
        dp=[[0]*(n+1) for _ in range(m+1)] # m+1行1 n+1列2
        for i in range(n+1):
            dp[0][i]=i*ic
        for i in range(m+1):
            dp[i][0]=i*dc
        for i in range(1,n+1):
            for j in range(1,m+1):
                if str1[j-1]==str2[i-1]:
                    dp[j][i]=dp[j-1][i-1]
                else:
                    dp[j][i]=min(dp[j-1][i-1]+rc,dp[j-1][i]+dc,dp[j][i-1]+ic)
        return dp[m][n]

题目二

描述

方法

动态规划,创建状态转移方程

注意 [1]*n 和 [1 for i in range(n)] 的结果是完全等价的

  • 初始化一维的不可变数据(如 0NoneFalse):优先使用 [0] * n,因为性能最好。
  • 初始化二维数组/嵌套列表(如动态规划 DP 表):必须使用 [[0] * m for _ in range(n)],千万不要用 [[0] * m] * n,否则会出现“改一行全跟着变”的 Bug。

代码

class Solution:
    def Fibonacci(self , n: int) -> int:
        # write code here
        if n==1 or n==2:
            return 1
        dp=[1]*n
        for i in range(2,n):
            dp[i]=dp[i-1]+dp[i-2]
        return dp[n-1]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值