Leetcode 290. Word Pattern & 291. Word Pattern II
来源:互联网 发布:安卓4.4.4 java模拟器 编辑:程序博客网 时间:2024/06/05 10:32
290. Word Pattern
Given a pattern
and a string str
, find if str
follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern
and a non-empty word in str
.
Examples:
- pattern =
"abba"
, str ="dog cat cat dog"
should return true. - pattern =
"abba"
, str ="dog cat cat fish"
should return false. - pattern =
"aaaa"
, str ="dog cat cat dog"
should return false. - pattern =
"abba"
, str ="dog dog dog dog"
should return false.
Notes:
You may assume pattern
contains only lowercase letters, and str
contains lowercase letters separated by a single space.
思路:
一个hashmap搞定。取出pattern的char, 则对应位置str[i]:要么value存在且相同;要么不存在value。如果无key,也无value,则加入map中。如果无key但是存在value,返回false。
public class Solution { public boolean wordPattern(String pattern, String str) { if (pattern.isEmpty() || str.isEmpty()) { return false; } String[] s = str.split(" "); if (s.length != pattern.length()) { return false; } HashMap<Character, String> hashMap = new HashMap<Character, String>(); for (int i = 0; i < pattern.length(); i++) { if (hashMap.containsKey(pattern.charAt(i))) { // 有pattern的char, 则对应value必须相等 if (!hashMap.get(pattern.charAt(i)).equals(s[i])) { return false; } } else if (hashMap.containsValue(s[i])) { // 如果没该char的key, 但是却有str中对应位置的单词,说明该单词是由别的char加入 return false; } else { hashMap.put(pattern.charAt(i), s[i]); } } return true; }}
291. Word Pattern II
Given a pattern
and a string str
, find if str
follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern
and a non-empty substring in str
.
Examples:
- pattern =
"abab"
, str ="redblueredblue"
should return true. - pattern =
"aaaa"
, str ="asdasdasdasd"
should return true. - pattern =
"aabb"
, str ="xyzabcxzyabc"
should return false.
Notes:
You may assume both pattern
and str
contains only lowercase letters.
思路:
UPDATE 9-25 之前没开会员,看得别人代码。现在开了做了一遍。写blog发现居然做过了,果然刷题将就的是过脑而不是单单的AC。完全没印象。
好久没debug这么久了。首先写了个dfs算法,用个hashmap保存已匹配的字符,然后如果无法匹配就backtracking。
逻辑大概是这样:dfs(pattern, 0, str, 0, map)
pattern的i位置去匹配str j位置。从m=j+1开始,取substring,然后去判断如下:
1. 如果map有这个key(chat at i in pattern),那么取出之后,当前j位置开始的字符串必须能匹配,否则return false回到上次循环;如果匹配了,那么j位置移动相应的位置,继续call dfs匹配。
2. 如果map里有value,那说明当前的substring被别的字符匹配了,需要跳过(continue)另取substring。
3. 到了这步,直接加入当前<char, substring>,然后继续call dfs。
思路很简单,结果 debug俩小时,卡在这个例子上:
"abab" 长度4
"redblueredblue" 长度14
返回了false。仔细检查逻辑写了如下log:
cur i j mr 0 0 1 无a这个key 放入(a, r) call 1e 1 1 2 无b这个key 放入(b, e) call 2d 2 2 3 有a这个key 和 get(a) = r 不相等 冲突直接return false call3, call2中删除( b, e)ed 1 1 3 无b这个key 放入(b, ed) call2。然后调用call 3.BUG ed没有放入b 2 3 4 有a这个key和get(a) = r不相等 call3返回false call2中删除(b, ed)edb 1 1 4 无b,放入(b, edb) call2 并调用call 3……edblue 1 1 7 放入(b, edblue) call 2中加入并调用call 3r 2 7 8 有a, get(a) == r call3发现match 修改m为e 3 8 9 有找到长度为6匹配
也就是说ed在上一次回溯之后没有放入。卡了好久,一步步分析逻辑和指针位置,最后灵机一动写了下面的代码(注释部分):
public class Solution { public boolean wordPatternMatch(String pattern, String str) { HashMap<Character, String> map = new HashMap<Character, String>(); if(dfs(pattern, 0, str, 0, map)) return true; else return false; } boolean dfs(String p, int i, String str, int j, HashMap<Character, String> map){ if(i == p.length() && j == str.length()) return true; if(i == p.length() || j == str.length()) return false; int m = j + 1; for(; m <= str.length(); m++){ String cur = str.substring(j, m); // if(cur.equals("ed")){ // System.out.println(cur + " " + i + " "+ j + " "+m); // System.out.println(map.containsKey(p.charAt(i))); // System.out.println(map.containsValue(cur)); // } if(map.containsKey(p.charAt(i))){ String match = map.get(p.charAt(i)); if(canFindMatch(str, match, j)){ m = j + match.length(); if(dfs(p, i + 1, str, m, map)) return true; } return false; // 当前key无法匹配 或者 当前key匹配之后后面仍无法匹配 }else if(map.containsValue(cur)){ continue; }else{ map.put(p.charAt(i), cur); if(dfs(p, i + 1, str, m, map)) return true; map.remove(cur); } } return false; } boolean canFindMatch(String s, String match, int i){ for(int j = 0; j < match.length(); j++){ if(s.charAt(i + j) != match.charAt(j)) return false; } return true; }}
发现卧槽,System.out.println(map.containsKey(p.charAt(i))) 居然为true。然后一看sb了,map remove(key)而不是 map remove(value).... 还好不是面试,这什么错误。。
还有个bug是canFindMatch应该提前判断i + j是否超过length,要不会OutOfBound,有可能在末尾匹配一个很长的字符串,所以要么先判断长度+位置是否超标再call,要么直接call里面设置一个判断。
最终版:
public class Solution { public boolean wordPatternMatch(String pattern, String str) { HashMap<Character, String> map = new HashMap<Character, String>(); if(dfs(pattern, 0, str, 0, map)) return true; else return false; } boolean dfs(String p, int i, String str, int j, HashMap<Character, String> map){ if(i == p.length() && j == str.length()) return true; if(i == p.length() || j == str.length()) return false; for(int m = j + 1; m <= str.length(); m++){ String cur = str.substring(j, m); if(map.containsKey(p.charAt(i))){ String match = map.get(p.charAt(i)); if(canFindMatch(str, match, j)){ m = j + match.length(); if(dfs(p, i + 1, str, m, map)) return true; } return false; // 当前key无法匹配 或者 当前key匹配之后后面仍无法匹配 }else if(map.containsValue(cur)){ continue; }else{ map.put(p.charAt(i), cur); if(dfs(p, i + 1, str, m, map)) return true; map.remove(p.charAt(i)); } } return false; } boolean canFindMatch(String s, String match, int i){ for(int j = 0; j < match.length(); j++){ if(i + j >= s.length()) return false; if(s.charAt(i + j) != match.charAt(j)) return false; } return true; }}
==================== 之前写的分界线 ===============================
programcreek上有很好的思路,discuss里也有很好的思路。
首先就是需要记录匹配的对应位置,比如pattern 1位置对应str的4。这个题肯定是要试所有的str substring组合可能性,所以必然是backtracking。
backtracking就一定是递归,参数是pattern, index位置1, str, index位置2。然后接下来可以传递一个参数或者俩参数。一个map保存<Char, String>,一个set保存String。
如参考文章中所说:
如果是一个参数:
首先对应index1, char c = pattern.charAt(i); 然后有两种情况。如果map中不含这个字符,说明该字符没有出现过,!!!并且在取str的substring时需要保证取到的substring没有出现过!!!!(比如ab, cc, a对应了c, 那么在match b的时候,右边是不能取到c的,因为这个c已经跟左边的a对应,然而b没出现过就是因为b!=a,所以b不能和现在这个c对应)。因此判断条件应为:
!map.containsKey(c) && !map.containsValue(sub);
如果是出现过那么当前取到的substring必须和保存的substring值相等:
map.containsKey(c) && map.get(c).equals(sub)
每次取一个字符去判断是否与c对应的string相等时:Since containsValue() method is used here, the time complexity is O(n). 于是提出了两参数,每次还要将匹配的substring放入 set,纯粹为了加快速度。
当无法匹配时,去除对应容器中的元素并返回false。
public boolean wordPatternMatch(String pattern, String str) { if(pattern.length()==0 && str.length()==0) return true; if(pattern.length()==0) return false; HashMap<Character, String> map = new HashMap<Character, String>(); return helper(pattern, str, 0, 0, map);} public boolean helper(String pattern, String str, int i, int j, HashMap<Character, String> map){ if(i==pattern.length() && j==str.length()){ return true; } if(i>=pattern.length() || j>=str.length()) return false; char c = pattern.charAt(i); for(int k=j+1; k<=str.length(); k++){ String sub = str.substring(j, k); if(!map.containsKey(c) && !map.containsValue(sub)){ map.put(c, sub); if(helper(pattern, str, i+1, k, map)) return true; map.remove(c); }else if(map.containsKey(c) && map.get(c).equals(sub)){ if(helper(pattern, str, i+1, k, map)) return true; } } return false;}
public boolean wordPatternMatch(String pattern, String str) { if(pattern.length()==0 && str.length()==0) return true; if(pattern.length()==0) return false; HashMap<Character, String> map = new HashMap<Character, String>(); HashSet<String> set = new HashSet<String>(); return helper(pattern, str, 0, 0, map, set);} public boolean helper(String pattern, String str, int i, int j, HashMap<Character, String> map, HashSet<String> set){ if(i==pattern.length() && j==str.length()){ return true; } if(i>=pattern.length() || j>=str.length()) return false; char c = pattern.charAt(i); for(int k=j+1; k<=str.length(); k++){ String sub = str.substring(j, k); if(!map.containsKey(c) && !set.contains(sub)){ map.put(c, sub); set.add(sub); if(helper(pattern, str, i+1, k, map, set)) return true; map.remove(c); set.remove(sub); }else if(map.containsKey(c) && map.get(c).equals(sub)){ if(helper(pattern, str, i+1, k, map, set)) return true; } } return false;}
- Leetcode 290. Word Pattern & 291. Word Pattern II
- LeetCode 291. Word Pattern II
- leetcode Word Pattern II
- [leetcode] 291. Word Pattern II 解题报告
- [Leetcode] 291. Word Pattern II 解题报告
- 【leetcode】290. Word Pattern
- 【leetcode】290. Word Pattern
- 290. Word Pattern LeetCode
- Leetcode 290. Word Pattern
- 【LeetCode】290. Word Pattern
- LeetCode-290. Word Pattern
- LeetCode *** 290. Word Pattern
- leetcode 290. Word Pattern
- LeetCode 290. Word Pattern
- LeetCode 290. Word Pattern
- [leetcode] 290. Word Pattern
- 【LeetCode】290. Word Pattern
- LeetCode-290.Word Pattern
- stl容器----vector
- Lua学习笔记Day2-Lua语法、值与类型、表达式、语句、函数
- tnsnames.ora
- iOS之Settings.Bundle
- 写在C语言开篇之前
- Leetcode 290. Word Pattern & 291. Word Pattern II
- cocos2d-x动画
- BZOJ2806-[Ctsc2012]Cheat
- 欧几里德及扩展欧几里德算法(学习)
- spring + spring mvc + mybatis框架整合的maven配置
- 支持读写分离、数据缓存、页面缓存的高性能PHP框架
- 微信公众平台 开发前准备
- IP地址转换总结
- springmvc之定时器