leetcode wordsearch II

来源:互联网 发布:男士钱包网络代理 编辑:程序博客网 时间:2024/05/22 17:48

做完word search之后,有一个类似的问题 word search II  与I不同的是,一为输入一个单词,判断单词是否在board里; II 中输入的是一组单词,返回在board中的所有单词。

Given a 2D board and a list of words from the dictionary, find all words in the board.

Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

For example,
Given words = ["oath","pea","eat","rain"] and board =

[  ['o','a','a','n'],  ['e','t','a','e'],  ['i','h','k','r'],  ['i','f','l','v']]
Return ["eat","oath"].

Note:
You may assume that all inputs are consist of lowercase letters a-z.

如果对每一个单词调用I的方法,则时间复杂度变得很高。所以考虑换一种方式。

I为遍历board[][]这个二维数组,查看是否存在该单词; II考虑通过字典树(TRIE)的方式,将输入的一组单词先形成字典树的形式,遍历board[][]二维数组的过程中,发现当前所组成的单词不是字典树中的prefix时,则立即结束,开始下一次探索。

这其中就涉及字典树(TRIE)的实现。

Implement a trie with insertsearch, and startsWith methods.

Note:
You may assume that all inputs are consist of lowercase letters a-z.

利用TrieNode[26] 来存储当前树节点的子节点。

isLeaf表明该节点是否为一个单词的最后一个char,用于区别startsWith和search

class TrieNode {    // Initialize your data structure here.    public TrieNode() {            }    private static final int MAX_NUMBER = 26;private char value;private boolean isLeaf = false;public TrieNode[] children = new TrieNode[MAX_NUMBER];public TrieNode(char value) {this.value = value;}public void setValue(char value) {this.value = value;}public char getValue() {return value;}public boolean isLeaf() {return isLeaf;}public void setLeaf(boolean isLeaf) {this.isLeaf = isLeaf;}public TrieNode[] getChildren() {return children;}public void setChildren(TrieNode[] children) {this.children = children;}}public class Trie {    private TrieNode root;    public Trie() {        root = new TrieNode();    }    // Inserts a word into the trie.    public void insert(String word) {        TrieNode tmpNode = root;for (int i = 0; i < word.length() ; i ++) {char c = word.charAt(i);if (tmpNode.children[c - 'a'] == null) {tmpNode.children[c - 'a'] = new TrieNode(c);}tmpNode = tmpNode.children[c - 'a']; }tmpNode.setLeaf(true);    }    // Returns if the word is in the trie.    public boolean search(String word) {        return search(root, word, 0);    }    // Returns if there is any word in the trie    // that starts with the given prefix.    public boolean startsWith(String prefix) {        return startsWith(root, prefix, 0);    }        private void insert(TrieNode root, String word) {if (word.length() == 0) {root.setLeaf(true);return;}char c = word.charAt(0);int index = c - 'a';TrieNode tmp = root.getChildren()[index];if (tmp == null) {tmp = new TrieNode();tmp.setValue(c);root.getChildren()[index] = tmp;} insert(root.getChildren()[index], word.substring(1));}private boolean search(TrieNode root, String word, int index) {if (root == null || word == null || index > word.length())return false;if (word.length() == index) {if (root.isLeaf())return true;else {return false;}}char c = word.charAt(index);TrieNode node = root.getChildren()[c - 'a'];if (node != null) {index += 1;if (search(node, word, index))return true;}return false;}private boolean startsWith(TrieNode root, String prefix, int index) {if (root == null || prefix == null || index > prefix.length())return false;if (prefix.length() == index)return true;char c = prefix.charAt(index);TrieNode node = root.getChildren()[c - 'a'];if ( node != null) {index += 1;if (startsWith(node, prefix, index))return true;} return false;}}

有了字典树,就可以解决上面的word search II问题

public class Solution {   public List<String> findWords(char[][] board, String[] words) {Trie trie = new Trie();for (String word : words) {trie.insert(word);}List<String> resultList = new ArrayList<String>();boolean[][] used = new boolean[board.length][board[0].length];for (int i = 0; i < board.length ; i ++) {for (int j = 0; j< board[0].length ; j++) {search(board, i,j, "", trie, used, resultList);}}return resultList;}private void search(char[][] board, int i, int j, String word, Trie trie,boolean[][] used, List<String> resultList) {if (i >= board.length || i < 0 || j >= board[0].length || j < 0|| used[i][j])return;word += board[i][j];if (!trie.startsWith(word))return;if (!resultList.contains(word) && trie.search(word)) {resultList.add(word);}used[i][j] = true;if (i + 1 < board.length)search(board, i+1, j, word, trie, used, resultList);if (i > 0)search(board, i-1, j, word, trie, used, resultList);if (j + 1 < board[0].length)search(board, i, j+1, word, trie, used, resultList);if (j > 0)search(board, i, j-1, word, trie, used, resultList);used[i][j] = false;}}

关键就是加了

if (!trie.startsWith(word))return;
这一步,使得不符合条件的可以提前终止。

0 0