给你一个字符数组,每个单词长度一样,你从中选单词,组成的 二位数组中 横向和纵向 组成的一维数组都一样。
注意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 主动选择 构建 每层节点,这样随着层数的增加 越到后面节点越少。