【程序员面试金典】面试题 01.05. 一次编辑

【程序员面试金典】面试题 01.05. 一次编辑

题目描述

描述:字符串有三种编辑操作:插入一个英文字符、删除一个英文字符或者替换一个英文字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。

输入: 
first = "pale"
second = "ple"
输出: True
输入: 
first = "pales"
second = "pal"
输出: False

解题思路

思路1:最直观的想法是,动态规划系列编辑距离问题,判断编辑距离是否小于等于1。其中dp[i][j]表示以first[i-1]结尾转换为以second[j-1]结尾所需的最少次数,其递推公式为:如果first[i-1]=second[j-1],则dp[i][j]=dp[i-1][j-1],反之不相等则dp[i][j]=min({dp[i][j-1],dp[i-1][j],dp[i-1][j-1]})+1。

    bool oneEditAway(string first, string second) {
        int n1=first.size();
        int n2=second.size();
        //dp[i][j]表示first[i-1]变成second[j-1]次数
        vector<vector<int>> dp(n1+1,vector<int>(n2+1,0));
        // second为空串
        for(int i=0;i<n1;i++) dp[i][0]=i;
        // first为空串
        for(int i=0;i<n2;i++) dp[0][i]=i;
        for(int i=1;i<=n1;i++)
        {
            for(int j=1;j<=n2;j++)
            {
                if(first[i-1]==second[j-1])
                    dp[i][j]=dp[i-1][j-1];
                else
                    dp[i][j]=min({dp[i][j-1],dp[i-1][j],dp[i-1][j-1]})+1;
            }
        }
        return dp[n1][n2]<=1;
    }

思路2:假设first长度为n1,second长度为n2,则一次编辑有三种情况:第一种是n1=n2,即first需要替换一个字符才能变成second;第二种是n1-n2=1,即first需要删除一个字符才能变成second;第三种是n2-n1=1,即first需要添加一个字符才能变成second;零次编辑有一种情况:即n1=n2且first与second完全相同。首先计算first和second的长度,并根据两者之间的长度关系来进行相应的处理。如果两者长度相同,则遍历字符串并逐个比较当前元素,再记录不同元素的个数,如果其大于1,则不可以一次编辑完成,反之可以;如果两者长度相差为1,则记录长串为longer,记录短串为shorter,使用双指针遍历两个字符串,如果相同则两个指针均后移,反之只将长串指针后移,如果长串与短串指针相差大于1,则不可以一次编辑完成,反之可以。

// 不可以处理长度相同的两个字符串 ab和bc无法判断
bool oneInsert(string longer,string shorter)
{
    int n1=longer.size();
    int n2=shorter.size();
    int index1=0;
    int index2=0;
    while(index1<n1&&index2<n2)
    {
        // 相等两者均后移
        if(longer[index1]==shorter[index2])
        {
            index1++;
            index2++;
        }
        // 不相等长串后移
        else
            index1++;
        // 相差大于1不可以一次编辑
        if(index1-index2>1)
            return false;
    }
    return true;
}
bool oneEditAway(string first, string second) 
{
    int n1=first.size();
    int n2=second.size();
    // 长度相差大于1则不可以一次编辑完成
    if(abs(n1-n2)>1) return false;
    int diff=n1-n2;
    // 删除
    if(diff==1) 
        return oneInsert(first,second);
    // 增加
    else if(diff==-1)
        return oneInsert(second,first);
    // 替换或者相同  ab bc
    int num=0;
    for(int i=0;i<n1;i++)
    {
        if(first[i]!=second[i])
        {
            num++;
            // 有两个或者两个以上不同则不可以一次编辑完成
            if(num>1) return false;
        }
    }
    return true;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值