290/291 Word Pattern I and II -- 290: map 291 map+backtracking

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;
    }
}

猜你喜欢

转载自www.cnblogs.com/keepAC/p/9976947.html
今日推荐