LeetCode(79 & 212):单词搜索 I II Word Search I II (Java)

234 篇文章 1 订阅
177 篇文章 0 订阅

2019.6.9 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)

第一题只要求对一个单词搜索,没什么好说的直接上回溯法就可以了。

关于回溯法的原理和其他实现可以看:

#数据结构与算法学习笔记#剑指Offer63:矩阵中的路径 + 回溯法(Java、C/C++)

#数据结构与算法学习笔记#剑指Offer64:机器人的运动范围 + 回溯法(Java、C/C++)

但是第二题要对多个单词进行搜索,要尽量提高搜索效率,避免多次重复回溯,可以用字典树。关于字典树的原理和标准实现可以看:

LeetCode(208):实现 Trie (前缀树) Implement Trie (Prefix Tree)(Java)

本题只要用一个简化版的字典树即可。


传送门:单词搜索

Given a 2D board and a word, find if the word exists in the grid.

The word can 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.

示例:
board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.

传送门:单词搜索 II

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.

给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例:
输入: 
words = ["oath","pea","eat","rain"] and board =
[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]
输出: ["eat","oath"]

说明:
你可以假设所有输入都由小写字母 a-z 组成。



import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * 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.
 * 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
 * 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
 *
 */

public class WordSearchII {
    //回溯法
    public List<String> findWords(char[][] board, String[] words) {
        ArrayList<String> result = new ArrayList<>();
        for(String str : words){
            if(exist(board, str)){
                result.add(str);
            }
        }
        return result;
    }

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

    public boolean Solution(char[][] board, String word, int loc, int x, int y, int rowlen, int collen, boolean[][] isVisited){
        if(loc == word.length()){
            return true;
        }
        if(x < 0 || x >= rowlen || y < 0 || y >= collen || isVisited[x][y] || board[x][y] != word.charAt(loc)){
            return false;
        }
        //小技巧,可用前后两次board[x][y] ^= 256代替isVisited功能
        isVisited[x][y] = true;
        boolean result = Solution(board, word, loc + 1, x - 1, y , rowlen, collen, isVisited)
                || Solution(board, word, loc + 1, x + 1, y , rowlen, collen, isVisited)
                || Solution(board, word, loc + 1, x, y - 1 , rowlen, collen, isVisited)
                || Solution(board, word, loc + 1, x, y + 1, rowlen, collen, isVisited);
        isVisited[x][y] = false;
        return result;
    }

    //字典树
    class TrieNode{
        public TrieNode[] children = new TrieNode[26];
        public String word = null;
    }

    class Trie{
        public TrieNode root = new TrieNode();
        public void insert(String word){
            TrieNode node = root;
            for(int i = 0; i < word.length(); i++){
                int charNum = word.charAt(i) - 'a';
                if(node.children[charNum] == null){
                    node.children[charNum] = new TrieNode();
                }
                node = node.children[charNum];
            }
            node.word = word;
        }
    }

    public List<String> findWords2(char[][] board, String[] words) {
        Trie trie = new Trie();
        for(String str : words){
            trie.insert(str);
        }
        boolean[][] isVisited = new boolean[board.length][board[0].length];
        HashSet<String> result = new HashSet<>();
        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[0].length; j++){
                search(board, isVisited, i , j, trie.root, result);
            }
        }
        return new LinkedList<>(result);
    }

    private void search(char[][] board, boolean[][] isVisited, int x, int y, TrieNode node, HashSet<String> result){
        if(x < 0 || x >= board.length || y < 0 || y >= board[0].length || isVisited[x][y]){
            return;
        }
        node = node.children[board[x][y] - 'a'];
        if(node == null){
            return;
        }
        if(node.word != null){
            result.add(node.word);
        }
        isVisited[x][y] = true;
        search(board, isVisited, x - 1, y, node, result);
        search(board, isVisited, x + 1, y, node, result);
        search(board, isVisited, x, y - 1, node, result);
        search(board, isVisited, x, y + 1, node, result);
        isVisited[x][y] = false;
    }
}




#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值