LeetCode.212 单词搜索 II(经典字典数+上下左右DFS问题模版)

3 篇文章 0 订阅
1 篇文章 0 订阅

原题

https://leetcode-cn.com/problems/word-search-ii/

在这里插入图片描述
在这里插入图片描述

思路

字典树 + DFS
1. 将words构造成一颗字典树(前缀树)
2. 上下左右DFSboard,如果在字典树中,记录每一次遍历到的字符,遇到结束字符,添加到结果集中


题解

package com.leetcode.code;

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

public class Code212 {

    public static void main(String[] args) {
        String[] words = {"hello", "world"};
        findWords(null, words);
    }

    // 上下左右移动的方向
    static int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public static List<String> findWords(char[][] board, String[] words) {
        // 结果集,去重
        Set<String> resultSet = new HashSet<>();

        // 构建字典树
        TrieNode root = buildTrie(words);

        // 获取board的行和列
        int row = board.length;
        int col = board[0].length;

        // 定义二维数组表示某个下标是否被访问过
        boolean[][] visited = new boolean[row][col];
        // 记录沿途遍历过的元素
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                dfs(resultSet, sb, board, i, j, root, visited);
            }
        }

        return new ArrayList<>(resultSet);
    }

    private static void dfs (Set<String> resultSet, StringBuilder sb, char[][] board, int i, int j, TrieNode node, boolean[][] visited) {
        // 判断越界、访问过、不在字典树中,直接返回
        if (i<0 || j<0 || i>=board.length || j>=board[0].length || visited[i][j] || node.children[board[i][j]-'a']==null) {
            return;
        }

        // 记录递归到的当前字符
        sb.append(board[i][j]);

        // 如果有结束字符,将当前sb添加到结果集中
        if (node.children[board[i][j]-'a'].isEnd) {
            resultSet.add(sb.toString());
        }

        // 记录当前元素已访问
        visited[i][j] = true;

        // 按照上下左右的方向递归board
        for (int[] dir : dirs) {
            dfs(resultSet, sb, board, i+dir[0], j+dir[1], node.children[board[i][j]-'a'], visited);
        }

        // 回溯,状态还原
        visited[i][j] = false;
        sb.deleteCharAt(sb.length()-1);
    }


    // 构建字典树
    private static TrieNode buildTrie(String[] words) {
        TrieNode root = new TrieNode();
        for (String word : words) {
            char[] arr = word.toCharArray();
            TrieNode curr = root;
            for (char c : arr) {
                if (curr.children[c - 'a'] == null) {
                    curr.children[c - 'a'] = new TrieNode();
                }
                curr = curr.children[c - 'a'];
            }
            curr.isEnd = true;
        }
        return root;
    }

}

class TrieNode{
    // 记录到这个节点是否是一个完整的单词
    boolean isEnd = false;
    // 孩子节点,题目说了都是小写字母,所以用数组,否则可以用HashMap替换
    TrieNode[] children = new TrieNode[26];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

难过的风景

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值