290 为一个简单题,但还是有个小坑的。
题意: 给你一个pattern 和 一个用空格split 的的str, 问你两边是否匹配。
Input: pattern ="abba"
, str ="dog cat cat dog"
Output: true
code 很简单,一看就是用Map, 去建立 char : string 之间的对应关系, 然而还得用一个 set 去保存已经存放的 string 了,例如:
pattern = "ab", str = "dog dog" 如果不用set 把现有的 string 都存放起来, 就可能导致两个字母 map 上一个 单词。
class Solution { public boolean wordPattern(String pattern, String str) { Map<Character, String> map = new HashMap<>(); Set<String> set = new HashSet<>(); String[] strs = str.split(" "); if(strs.length != pattern.length()) return false; for(int i=0; i<pattern.length(); i++){ char c = pattern.charAt(i); if(map.containsKey(c) && !map.get(c).equals(strs[i])) return false; if(!map.containsKey(c)) { if(set.contains(strs[i])) return false; map.put(c,strs[i]); set.add(strs[i]); } } return true; } }
还得注意字符处理中两个细节:
1. str.split(” “) 来把单词给差分开
2. 字符串相等 用equals, 而不是 == ,一开始写成这样导致出错。
291. 和 290 类似,也是让你看 pattern 和 str 是否能匹配, 唯一区别: 没有用 空格去区分单词,而是让你自己去拆分。 虽然就是一点差别,难度却千差万别了。
用back tracking 去 try 每一种情况,然后去看是否有匹配的。
主要的麻烦就是,如何把这个dfs 写的简单明了, 第一个版本的code 写成了这样:当然第一个版更高效一点,但code 写的实在太冗余了。
class Solution { public boolean wordPatternMatch(String pattern, String str) { // Map<Character, String> map = new HashMap<>(); String[] map = new String[256]; for(int i=0; i<map.length; i++) map[i] = ""; int len = str.length(); int[] nums = new int[len]; for(int i=0; i<len; i++) nums[i] = i+1; return dfs(map,nums,pattern,str,0,0, new HashMap<>()); } private boolean dfs(String[] map, int[] nums, String pattern, String str, int index, int start, Map<String,Integer> dic){ if(start == str.length() && index == pattern.length()){ return true; } if(index >= pattern.length()) return false; if(start > str.length()){ return false; } boolean flag = false; int letter = (int)pattern.charAt(index); // System.out.println(letter); if(!map[letter].equals("")){ if(start+map[letter].length() > str.length()) return false; String next_str = str.substring(start, start+map[letter].length()); if(!next_str.equals(map[letter])) return false; start += map[letter].length(); flag = flag || dfs(map,nums,pattern, str,index+1,start,dic); if(flag) return true; start -= map[letter].length(); } else { for(int i=0; i<nums.length; i++){ if(start+nums[i] > str.length()) return false; String try_str = str.substring(start,start+nums[i]); if(dic.containsKey(try_str) && dic.get(try_str)!= letter) continue; map[letter] = try_str; dic.put(try_str,letter); start += nums[i]; flag = flag || dfs(map,nums,pattern, str, index+1,start,dic); if(flag) return true; start -= nums[i]; map[letter] = ""; dic.remove(try_str); } } return flag; } }
最终版本code 长这样:注意这里 1.
for(int end=index_s; end< str.length(); end++) 表示每次结尾的 index, 每次截取字符串用 str.substring(index_s,end+1);
就避免了 一开始我写的:先得判断增加的长度是否溢出,再截取字符串的冗余了。
if(start+nums[i] > str.length()) return false; String try_str = str.substring(start,start+nums[i]);
2. 还有return 的设计:一开始我用了这样的写法
flag = flag || dfs(map,nums,pattern, str, index+1,start,dic);
if(flag) return true;
真是多此一举呀,直接 if(dfs(map,nums,pattern, str, index+1,start,dic)) return true 不是更好么?
3. if(dfs(map,pattern, str, index_p+1,end+1,dic)) 注意这里end 表示结尾的 index, 因此下一次dfs 时 传递的都是 end+1 即可
class Solution { public boolean wordPatternMatch(String pattern, String str) { return dfs(new HashMap<>(),pattern,str,0,0, new HashSet<>()); } private boolean dfs(Map<Character,String> map, String pattern, String str, int index_p, int index_s, Set<String> dic){ if(index_s == str.length() && index_p == pattern.length()){ return true; } if(index_p == pattern.length() ||index_s == str.length() ) return false; //这里得包含 = , 否则过不了 "" "s" 的case char letter = pattern.charAt(index_p); if(map.containsKey(letter)){ String val = map.get(letter); if (!str.startsWith(val, index_s)) { return false; } if(dfs(map,pattern, str,index_p+1,index_s+val.length(),dic)) return true; } else { for(int end=index_s; end< str.length(); end++){ String try_str = str.substring(index_s,end+1); if(!map.containsKey(letter) && dic.contains(try_str) ) continue; // 不能return false, 例如 "aba" "aaaa", 应该return true map.put(letter, try_str); dic.add(try_str); if(dfs(map,pattern, str, index_p+1,end+1,dic)) return true; map.remove(letter); dic.remove(try_str); } } return false; } }