[LeetCode#161] One Edit Distance
2015-09-17 08:58
465 查看
Problem:
Given two strings S and T, determine if they are both one edit distance apart.
General Analysis:
Wrong Solution 1:
Mistake Analysis:
Inefficient Solution 1:
Analysis:
Efficient Solution 1:
Improve Analysis:
Upgraded Solution:
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; } }
相关文章推荐
- 51nod 1191:消灭兔子 贪心+优先队列
- andriod之自定义适配器与ListView的优化:
- linux下网站文件的自动备份
- Filter里面注入Service方法
- iOS疯狂讲解之复杂对象的归档与反归档
- 欢迎使用CSDN-markdown编辑器
- 网易互联网2015 在线笔试(2)
- 网易互联网2015 在线笔试(2)
- 全文检索之中文分词
- 核心动画基础动画(CABasicAnimation)关键帧动画
- 证书、描述文件、App ID的解释
- Linux达人养成计划I——linux命令格式
- vs2015
- SIFT GPU 优化思路整理
- android Spinner控件详解
- lintcode做题总结, Sept 15
- lintcode-删除排序链表中的重复数字II-113
- UI中对于选择主题的处理方法
- 正则表达式之group
- MFC去掉窗口右上方最大化最小化关闭按钮