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. Android测试分析二

    什么是android测试,分为黑盒测试和白盒测试. 黑盒就是测试人员看不到代码的,针对需求而进行的一系列测试动作,看代码所展现出来的效果是否和需求一样,或者有什么意外的情况没有处理等,一般开发交给测试 ...

  2. 那天有个小孩跟我说LINQ(四)转载

    1  LINQ TO SQL(代码下载)       我们以一个酒店管理系统的数据库为例子         表结构很简单:GuestInfo(客人信息表),Room(房间表),RoomType(房间类 ...

  3. [python] 字符串与列表、字典的转换

    1.字符串->字典:eval(str) 2.字符串->列表:list(str)

  4. xcode 最近打开文件列表显示为空或不显示最近打开的项目或(no recent projects)解决办法

    如果使用的是10.10 系统,打开系统设置-->进入通用-->在最下面的"最近使用的项目"中将0改为你可以接受的选项 如果不是10.10,那么就从系统偏好设置---&g ...

  5. yum 安装 依赖报错

    今天使用yum安装的时候 报错: Error: Multilib version problems found. This often means that the root cause 应该是yum ...

  6. Linux的关机与重启命令

    Linux的关机与重启命令 作者: Aillo, 发布于2009-05-10, 在系统分类下, 1条留言. 重启命令:1.reboot2.shutdown -r now 立刻重启(root用户使用)3 ...

  7. 利用iptables来配置linux禁止所有端口登陆和开放指定端口

    from:http://www.myhack58.com/Article/sort099/sort0102/2011/31781.htm 1.关闭所有的 INPUT FORWARD OUTPUT 只对 ...

  8. sar监控系统状态

    sar 命令很强大,它可以监控系统所有资源状态,比如平均负载.网卡流量.磁盘状态.内存使用等等. 它不同于其他系统状态监控工具的地方在于,它可以打印历史信息,可以显示当天从零点开始到当前时刻的系统状态 ...

  9. centos 软件安装 删除

    centos的软件安装大致可以分为两种类型: [centos]rpm文件安装,使用rpm指令  类似[ubuntu]deb文件安装,使用dpkg指令 [centos]yum安装   类似[ubuntu ...

  10. node开子线程模块--tagg2

    tagg2包同样具有tagg包的多线程功能,采用新的node-gyp命令进行编译,同时它跨平台支持,mac,linux,windows下都可以使用,对开发人员的api也更加友好.安装方法很简单,直接n ...