Problem:

Given two strings S and T, determine if they are both one edit distance apart.

General Analysis:

This problem is not hard. However, to write out more efficient and elegant solution, we need to dive more deep to understand the logic behind it. 

Instant idea:
1. The length difference betweeen string "s" and string "t" must not longer than 1, otherwise, no one edit operation could make them same. (at least two insert or two delete actions)
2. For it is valid, it could be following cases:
2.1 s.length() == t.length()
s and t have only one character in difference. 2.2 s.length() == t.length() - 1 (s.length() < t.length())
a. insert one character into s.
b. append one charcter after s. Note: append one charcter after s is strange, it could easily break your solution!

Wrong Solution 1:

public class Solution {
public boolean isOneEditDistance(String s, String t) {
int s_len = s.length();
int t_len = t.length();
if (s_len == 0 && t_len == 0)
return false;
if (Math.abs(s_len - t_len) > 1) {
return false;
} else if(Math.abs(s_len - t_len) == 1) {
String longer = s;
String shorter = t;
if (s_len < t_len) {
longer = t;
shorter = s;
}
for (int i = 0; i < longer.length(); i++) {
String new_longer = longer.substring(0, i) + longer.substring(i+1);
if (new_longer.equals(shorter))
return true;
}
} else{
int diff_count = 0;
for (int i = 0; i < s_len; i++) {
if (s.charAt(i) != t.charAt(i))
diff_count++;
}
if (diff_count != 1)
return false;
}
return true;
}
}

Mistake Analysis:

Input:
"", ""
Output:
true
Expected:
false Mistakes:
The above solution must be wrong!!! How could you mixed "return false" and "return true" in the middle of code! It could easily break your logic.

Inefficient Solution 1:

public class Solution {
public boolean isOneEditDistance(String s, String t) {
int s_len = s.length();
int t_len = t.length();
if (s_len == 0 && t_len == 0)
return false;
if (Math.abs(s_len - t_len) > 1) {
return false;
} else if(Math.abs(s_len - t_len) == 1) {
String longer = s;
String shorter = t;
if (s_len < t_len) {
longer = t;
shorter = s;
}
for (int i = 0; i < longer.length(); i++) {
String new_longer = longer.substring(0, i) + longer.substring(i+1);
if (new_longer.equals(shorter))
return true;
}
} else{
int diff_count = 0;
for (int i = 0; i < s_len; i++) {
if (s.charAt(i) != t.charAt(i))
diff_count++;
}
if (diff_count == 1)
return true;
}
return false;
}
}

Analysis:

Even though the above solution was accepted, it is quite slow. Cause for the case of "s.length() == t.length() - 1", we have tried to delete each character in the t. which actually is quite uncessary!!!! 

What's more, I have a ugly code to assgin the longer and shorter string.
--------------------------------------------------------------
String longer = s;
String shorter = t;
if (s_len < t_len) {
longer = t;
shorter = s;
}
---------------------------------------------------------------
Which could be smartly written as
if (t_len < s_len)
return isOneEditDistance(t, s);
It means s is always the shorter String. Improve analysis:
Actually the above solution is really really ugly, we consturct a new string and make the compare every time. The efficiency is unacceptable! There actually could be a more easy way to do it!
We know we actually could only do two things to make two string equal, one is to insert a new character in to the shorter string s or replace one character in s. And the two actions were only allowed to perform once! Basic idea:
We compare the characters in s and t one by one. Once we detect a difference, we try to use following two ways to fix it.
1. insert the difference character into s.
String inserted = (s.substring(0, i) + t.charAt(i) + s.substring(i));
2. reaplce the character in s.
String replaced = (s.substring(0, i) + t.charAt(i) + s.substring(i+1)); If one of them works, it means we could use only one edit to make those two string equal. However if both of them fail, we should return false!!!<Since we only allowed to do one edit, and the conflict at current position could not be simply solved by one edit> In the case of there is no difference in common length part of s and t, we should also distinguish following two cases:
1. s == t, which should return false.
2. s == t + 1, which should return true, since we could append one character after s to make them same. while (i < s_len && j < t_len) {
if (s.charAt(i) != t.charAt(j)) {
...
return replaced.equals(t) || inserted.equals(t);
}
...
return s_len + 1 == t_len;

Efficient Solution 1:

public class Solution {
public boolean isOneEditDistance(String s, String t) {
int s_len = s.length();
int t_len = t.length();
if (t_len < s_len)
return isOneEditDistance(t, s);
if (t_len - s_len > 1)
return false;
int i = 0;
int j = 0;
while (i < s_len && j < t_len) {
if (s.charAt(i) != t.charAt(j)) {
String replaced = (s.substring(0, i) + t.charAt(i) + s.substring(i+1));
String inserted = (s.substring(0, i) + t.charAt(i) + s.substring(i));
return replaced.equals(t) || inserted.equals(t);
}
i++;
j++;
}
return s_len + 1 == t_len;
}
}

Improve Analysis:

The aove solution could be written in a more elegant way.
1. use only one index i, since until we return the result, i and j share the same start and pace.
int i = 0;
int j = 0;
while (i < s_len && j < t_len) {
...
i++;
j++;
} 2. no need to compare the suppposed common part among s and t.
String replaced = (s.substring(0, i) + t.charAt(i) + s.substring(i+1));
String inserted = (s.substring(0, i) + t.charAt(i) + s.substring(i));
return replaced.equals(t) || inserted.equals(t); Since s.substring(0, i) is common is s and t. any after the edits, t.charAt(i) was inserted/replaced into s. We absolutely have no need to compare them again.
if (s.charAt(i) != t.charAt(i))
return s.substring(i+1).equals(t.substring(i+1)) || s.substring(i).equals(t.substring(i+1));

Upgraded Solution:

public class Solution {
public boolean isOneEditDistance(String s, String t) {
int s_len = s.length();
int t_len = t.length();
if (t_len < s_len)
return isOneEditDistance(t, s);
if (t_len - s_len > 1)
return false;
int i = 0;
while (i < s_len) {
if (s.charAt(i) != t.charAt(i))
return s.substring(i+1).equals(t.substring(i+1)) || s.substring(i).equals(t.substring(i+1));
i++;
}
return s_len + 1 == t_len;
}
}

[LeetCode#161] One Edit Distance的更多相关文章

  1. [LeetCode] 161. One Edit Distance 一个编辑距离

    Given two strings s and t, determine if they are both one edit distance apart. Note: There are 3 pos ...

  2. [leetcode]161. One Edit Distance编辑步数为一

    Given two strings s and t, determine if they are both one edit distance apart. Note: There are 3 pos ...

  3. ✡ leetcode 161. One Edit Distance 判断两个字符串是否是一步变换 --------- java

    Given two strings S and T, determine if they are both one edit distance apart. 给定两个字符串,判断他们是否是一步变换得到 ...

  4. 【LeetCode】161. One Edit Distance

    Difficulty: Medium  More:[目录]LeetCode Java实现 Description Given two strings S and T, determine if the ...

  5. 161. One Edit Distance

    题目: Given two strings S and T, determine if they are both one edit distance apart. 链接: http://leetco ...

  6. [LeetCode] 161. One Edit Distance_Medium

    Given two strings s and t, determine if they are both one edit distance apart. Note: There are 3 pos ...

  7. 【Leetcode】72 Edit Distance

    72. Edit Distance Given two words word1 and word2, find the minimum number of steps required to conv ...

  8. [LC] 161. One Edit Distance

    Given two strings s and t, determine if they are both one edit distance apart. Note: There are 3 pos ...

  9. leetcode@ [72/115] Edit Distance & Distinct Subsequences (Dynamic Programming)

    https://leetcode.com/problems/edit-distance/ Given two words word1 and word2, find the minimum numbe ...

随机推荐

  1. 20151205 jquery 学习笔记--Ajax

    Ajax全称为:“Asynchronous JavaScript and XML”(异步 JavaScript 和 XML), 它并不是 JavaScript 的一种单一技术,而是利用了一系列交互式网 ...

  2. exists改写SQL,使其走正确的执行计划

    数据库环境:SQL SERVER 2005 今天看到一条SQL,写得不是很复杂,返回7000多条数据,却执行了15s.SQL文本及各表的数据量如下: SELECT acinv_07.id_item , ...

  3. Gradle实战教程之依赖管理

    这是从我个人网站中复制过来的,原文地址:http://coolshell.info/blog/2015/05/gradle-dependency-management.html,转载请注明出处. 简要 ...

  4. Codeforces Round #299 (Div. 1)

    Problem A: 实际上对于一段数字假设和为k,每次取较大的m个进行t次减一操作,最多减去的是min(m*t,k). 明白了这个结论就可以直接二分答案了. #include <bits/st ...

  5. /var子目录

    /var子目录 目录 描述 /var/log/message 日志信息,按周自动轮询 /var/spool/cron/root 定时器配置文件目录,默认按用户命名 /var/log/secure 记录 ...

  6. PHP类中的__get()和__set函数到底有什么用?

    当试图获取一个不可达变量时,类会自动调用__get. 同样的,当试图设置一个不可达变量时,类会自动调用__set. 在网站中,这两个并不是什么非用不可的函数.   例如: Class Test {   ...

  7. ES6笔记-正则表达式和字符串正则方法

    RegExp构造函数 在ES5中,RegExp构造函数的参数有两种情况. 第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag). var regex = new RegExp( ...

  8. C#面向对象的学习笔记

    1.面向对象的3要素: 封装:将不需要显示的代码封装到一个方法中,只对外提供方法名,用户不需关心内部实现. 继承:子类继承父类,公用父类的代码,大大提高了代码的重用,贴近生活也符合人类的编程思想. 多 ...

  9. PHP正则表达式 验证电子邮件地址

    我们最经常遇到的验证,就是电子邮件地址验证.网站上常见.各种网页脚本也都常用“正则表达式”(regular expression)对我们输入的电子邮件地址进行验证,判断是否合法.有的还能分解出用户名和 ...

  10. php验证复选框有效性的示例

    本文介绍一个简单的php通过代码验证复选框值的有效性,有需要的可以参考一下 验证复选框的php代码,如下: 复制代码代码如下: <?php   /**   * 在php中验证复选框的有效性  * ...