# 1554. Strings Differ by One Character ###### tags: `Leetcode` `FaceBook` `Medium` ## 思路 ### 思路一 $O(N * M^2)$ N是dict的长度 M是每个string的长度 和[0127. Word Ladder](https://hackmd.io/2F_Qo1tWSH2QKrMp6USYEw)思路有点像 把每个字符串的每个位置挖掉,然后放进set里面 **时间复杂度是因为 concatenation of two strings takes O(m1 + m2) time.** ### 思路二 Trie $O(M * N)$ ### 思路三 String Hash $O(M * N)$ 通过给字符串编码,再放进hashset里面,进而找重复的 这里的mod是实验试出来,理论上来说YOU CAN NOT AVOID COLLISION COMPLETELY. 如果第16行和第18行的回圈倒着写,且不加set.clear()就会出错,例如遇到aaade这个字符串第一次删第一个a,会产生aade,第二次删第二个a,还是会产生aade,就会出错,所以需要先遍历各个位置,再遍历每个字符串,每次换位置的时候把set清空 第一个思路不会遇到这个问题是因为用```*```标示除了到底是哪个字符被拿掉了 所以上面的case,会产生```*aade,a*ade,aa*de``` ## Code ### 思路一 ```java= class Solution { public boolean differByOne(String[] dict) { Set<String> set = new HashSet<>(); for(int i = 0;i < dict.length;i++){ String str = dict[i]; for(int j = 0;j < str.length();j++){ String t = str.substring(0,j)+"*"+str.substring(j+1, str.length()); if(set.contains(t)){ return true; } set.add(t); } } return false; } } ``` ### 思路二 Trie ```java= class Solution { class TrieNode{ TrieNode[] children = new TrieNode[26]; boolean end = false; } TrieNode root; public boolean differByOne(String[] dict) { root = new TrieNode(); int n = dict.length; for(int i=0; i<n; i++){ add(dict[i]); } for(int i=0; i<n; i++){ if(dfs(dict[i], 0, 0, root)) return true; } return false; } private void add(String s){ TrieNode curr = root; for(int i=0; i<s.length(); i++){ if(curr.children[s.charAt(i)-'a']==null) curr.children[s.charAt(i)-'a'] = new TrieNode(); curr = curr.children[s.charAt(i)-'a']; } curr.end = true; } private boolean dfs(String s, int diff, int idx, TrieNode curr){ if(curr==null) return false; if(idx>=s.length()){ return diff==1 && curr.end; } if(diff>1) return false; for(int i=0; i<26; i++){ if(curr.children[i]==null) continue; if(i==s.charAt(idx)-'a'){ if(dfs(s, diff, idx+1, curr.children[i])) return true; } else if(dfs(s, diff+1, idx+1, curr.children[i])) return true; } return false; } } ``` ### 思路三 String Hash ```java= class Solution { public boolean differByOne(String[] dict) { Set<Long> set = new HashSet<>(); long mod = (long) Math.pow(10, 20) + 7; int len = dict[0].length(); long[] word2hash = new long[dict.length]; for(int i = 0;i < dict.length;i++){ String str = dict[i]; for(int j = 0;j < str.length();j++){ word2hash[i] = (word2hash[i]*26 + (str.charAt(j)-'a'))%mod; } } long base = 1; for (int j = len - 1; j >= 0; j--) { set.clear(); for (int i = 0; i < dict.length; i++) { long newHash = (word2hash[i] - base * (dict[i].charAt(j)-'a')) % mod; if (set.contains(newHash)) { return true; } set.add(newHash); } base = 26 * base % mod; } return false; } } ```