面试题 01.05. 一次编辑

150 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

  • 字符串有三种编辑操作:插入一个字符、删除一个字符或者替换一个字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。 示例 1
输入: 
first = "pale"
second = "ple"
输出: True

示例 2

输入: 
first = "pales"
second = "pal"
输出: False

思路分析

  • 字符串的变换一共有三种:插入一个字符、删除一个字符和替换一个字符,其中插入和删除字符都会改变一个字符串的长度。
  • 我们要维护字符串修改的次数,所以在这里可以用动态规划也可以用递归回溯剪枝。具体见 AC 代码。
  • 例如,以 firstfirst 字符串为标准。
  • firstfirstsecondsecond 在对应位置 indexindex 字符不同时。
  1. 删除 fisrtfisrt 该位置上的字符,此时 firstfirst 对应的 indexindex 变为 indexindex + 1 ,secondsecond 对应的 indexindex 不变。
  2. 插入 firstfirst 该位置上 secondsecond 字符对应的字符,此时 firstfirst 对应的 indexindex 不变,secondsecond 对应的 indexindex 变为 indexindex + 1 。
  3. 替换 firstfirst secondsecond 任意字符对应位置的字符即可,此时 firstfirstsecondsecond 对应的 indexindex 都要变为 indexindex + 1。

AC 代码

class Solution {
    char[] f;
    char[] s;
    int nf;
    int ns;
    public boolean oneEditAway(String first, String second) {
        f = first.toCharArray();  // 转为字符数组,访问字符数组速度要远快于访问字符串的速度.
        s = second.toCharArray();
        nf = f.length;
        ns = s.length;
        if (Math.abs(nf - ns) >= 2) return false;
        return dfs(0,0,0);
    }

    private boolean dfs(int index_f, int index_s, int count) {
        if (count >= 2) return false;  // 当修改字符的次数大于等于 2 次时不符合题意.
        if (index_f >= nf && index_s >= ns) return true;  // 修改次数小于 2 , 且两字符一致.
        else if (index_f >= nf) {
            if (count == 1) return false;  // 此处肯定要进行一次插入或者删除,之前已经有过一次修改,所以不符合题意.
            int sub = ns - index_s;
            return sub <= 1; // 所要修改的次数应该要小于等于 1 次.
        } else if (index_s >= ns) { // 分析同上.
            if (count == 1) return false;
            int sub = nf - index_f;
            return sub <= 1;
        }
        if (f[index_f] == s[index_s]) {
            return dfs(index_f + 1, index_s + 1,count);
        } else {  // 以下是对 f 进行操作.
            return dfs(index_f + 1, index_s, count + 1) ||  // 删除.
                   dfs(index_f, index_s + 1, count + 1) ||  // 插入.
                   dfs(index_f + 1, index_s + 1, count + 1); // 替换.
        }
    }
}

总结

  • 这道题按照常规思路应该是用动态规划来做的,但是刚好可以可以用回溯解决,且回溯方法相比于动态规划更简单、更容易理解!