资讯专栏INFORMATION COLUMN

212. Word SearchII

hoohack / 2763人阅读

摘要:题目解答这题我原来是在的基础上,用来做的,代码如下做完之后,结果运行是对的,但是了,所以肯定是有更好的办法。代码如下去重

题目:
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"].

解答:
这题我原来是在word search I的基础上,用backtracking来做的,代码如下:

public boolean exist(char[][] board, String word, int i, int j, int pos, boolean[][] visited) {
    if (pos == word.length()) return true;
    if (i < 0 || i > board.length - 1 || j < 0 || j > board[i].length - 1) return false;
    if (visited[i][j] || board[i][j] != word.charAt(pos)) return false;
    
    visited[i][j] = true;
    int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    for (int k = 0; k < dir.length; k++) {
        int x = i + dir[k][0], y = j + dir[k][1];
        if (exist(board, word, x, y, pos + 1, visited)) {
            return true;
        }
    }
    visited[i][j] = false;
    return false;
}

public boolean helper(char[][] board, String word) {
    boolean[][] visited = new boolean[board.length][board[0].length];
    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[i].length; j++) {
            if (exist(board, word, i, j, 0, visited)) {
                return true;
            }
        }
    }
    return false;
}

public List findWords(char[][] board, String[] words) {
    List result = new ArrayList();
    if (board == null || board.length == 0 || board[0].length == 0) return result;
 
    for (String word : words) {
        if (helper(board, word)) {
            if (!result.contains(word)) {
                result.add(word);
            }
        }
    }
    
    return result;
}

做完之后,结果运行是对的,但是TLE了,所以肯定是有更好的办法。在TLE的test case里,我看到是当prefix相同时,如果用backtracking那么会不断地扫同一个位置的prefix,非常的冗余,那么怎么把prefix提取出来只扫一次呢?一个很好的办法就是反过来,用trie树先把单词存起来,然后扫board,扫board的时候用trie树中的可能出现的单词作为限制条件,那么当扫到一个trie中结尾存在的单词时,把它存进result中去。代码如下:

class TrieNode {
    TrieNode[] next = new TrieNode[26];
    String word;
}

public TrieNode buildTrie(String[] words) {
    TrieNode root = new TrieNode();
    for (String word : words) {
        TrieNode p = root;
        for (char c : word.toCharArray()) {
            int i = c - "a";
            if (p.next[i] == null) p.next[i] = new TrieNode();
            p = p.next[i];
        }
        p.word = word;
    }
    return root;
}

public void dfs(List result, char[][] board, TrieNode p, int i, int j) {
    char c = board[i][j];
    if (c == "#" || p.next[c - "a"] == null) return;
    p = p.next[c - "a"];
    
    if (p.word != null) {
        result.add(p.word);
        p.word = null; //去重
    }
    
    board[i][j] = "#";
    int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    for (int k = 0; k < dir.length; k++) {
        int x = i + dir[k][0], y = j + dir[k][1];
        if (x < 0 || x > board.length - 1 || y < 0 || y > board[i].length - 1) continue;
        dfs(result, board, p, x, y);
    }
    board[i][j] = c;
}

public List findWords(char[][] board, String[] words) {
    List result = new ArrayList();
    if (board == null || board.length == 0 || board[0].length == 0) return result;
    
    TrieNode root = buildTrie(words);
    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[i].length; j++) {
            dfs(result, board, root, i, j);
        }
    }
    return result;
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64976.html

相关文章

  • [LeetCode] 212. Word Search II

    Problem 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 ...

    Flands 评论0 收藏0
  • Vim session

    摘要:练级攻略的纵向编辑模式第一步修改将数列中第二段所有数字修改为将游标定位第一个行的进入纵向编辑模式移动游标到最后一行,可视块覆盖所要修改的列进入修改模式输入数字第二步前添加在所有行之前添加将游标定位到第一行第一列进入纵向编辑模式 vimtutor showImg(https://segmentfault.com/img/bV4OLS?w=600&h=400); intro vim hi...

    nanfeiyan 评论0 收藏0
  • Bind进阶

    摘要:子域授权比如我的一台服务器负责的权威域名解析,它再授权服务器对的子域名进行解析,这就叫做子域授权。之后,通过自己的会话密钥将要发送的明文进行加密,发送给,通过事先得到的会话密钥对发送过来的密文进行解密从而得到明文。 还是出于项目的需要,把Bind比较高级的功能做一个梳理,这其中包含:DNS递归迭代查询、DNS子域授权、DNS转发、DNS主从区域传输、DNS数据加密,每一个内容不仅记录了...

    doodlewind 评论0 收藏0

发表评论

0条评论

阅读需要支付1元查看
<