425. Word Squares -- back tracking + trie tree(TLE if not)

给你一个字符数组,每个单词长度一样,你从中选单词,组成的 二位数组中 横向和纵向 组成的一维数组都一样。

注意1: 单词可以重复被选择

注意2. 字符串数组可能非常的大,有1000 个

Input:
["area","lead","wall","lady","ball"]

Output:
[
  [ "wall",
    "area",
    "lead",
    "lady"
  ],
  [ "ball",
    "area",
    "lead",
    "lady"
  ]
]

分析一: 既然单词可以重复,那就是一个组合问题,每个节点上的下一个节点都可以分解成 数组里全部元素, 如果单词长度为5, array 里有1000个单词,那么 最后一层就有 1000^5个节点,很容易TLE。 dfs 树为:

分析二:  假设单词当都为5, 第一个单词任意放, 第二个单词首字母 [1][0]位置 会被 第一个单词 [0][1] 位置所决定。

                 第三个word 前两个字母, [2][0], [2][1] 会被 [0][2],[1][2] 位置所决定, 以此内推。

 针对这个特性,可以有两个方案:

1. 在普通dfs 中, 放 第 i个word 时, 先判断 前 i-1个letters 是否合法,不合法则不放。

2. 用Trie , 每次主动选prefix 满足条件的单词来构建。比如构建 第3个单词时, 得看 20,21 位置作为prefix 来主动选择单词。

对于方案一,代码很容易,但当 array 里面数量很大,因为着每一层节点都很多时,会TLE, code 如下:  15/16, 16个tests 过了15个,最后一个会TLE。

class Solution {
    public List<List<String>> wordSquares(String[] words) {
        
        List<List<String>> result = new ArrayList<>();
      
        dfs(new ArrayList<>(), result, words); 
        return result;
    }
    
   private void dfs(List<String> curResult, List<List<String>> result, String[] words){
       if(curResult.size() == words[0].length()){
           result.add(new ArrayList<>(curResult));
           return;
       }
       //if(depth >= words[0].length()) return;
       
       for(int i=0; i<words.length; i++){
          
               if(!validPut(curResult,words[i])) continue;
            
               dfs(curResult,result,words);
              
               curResult.remove(curResult.size()-1);
          
       }
   }
    
    private boolean validPut(List<String> curResult, String word){
        int size = curResult.size();
        for(int i=0; i<size; i++){
            if(word.charAt(i) != curResult.get(i).charAt(size) ) return false; 
        }
     
        curResult.add(word);
       //  System.out.println(curResult);
        return true;
    }
}

为了不TLE, 只能选择用 Trie Tree 主动选择 构建 每层节点,这样随着层数的增加 越到后面节点越少。



猜你喜欢

转载自www.cnblogs.com/keepAC/p/9992894.html