学习记录:js算法(六十二):单词搜索 II

news2024/12/26 22:22:17

文章目录

    • 单词搜索 II
      • 思路一
      • 思路二

单词搜索 II

给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words, 返回所有二维网格上的单词 。
单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

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

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

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

示例 2:图二
输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]

思路一

var findWords = function(board, words) {
    const root = {};
    const result = [];

    // 构建字典树
    words.forEach(word => {
        let node = root;
        for (const char of word) {
            if (!node[char]) {
                node[char] = {};
            }
            node = node[char];
        }
        node.end = word;
    });

    // DFS 搜索函数
    const dfs = (node, i, j, str) => {
        const char = board[i][j];
        if (char === '#' || !node[char]) {
            return;
        }
        str += char;
        node = node[char];

        if (node.end) {
            result.push(node.end);
            delete node.end; // 防止重复添加
        }

        // 四个方向搜索
        const directions = [[0,1], [0,-1], [1,0], [-1,0]];
        directions.forEach(([dx, dy]) => {
            const ni = i + dx;
            const nj = j + dy;
            if (ni >= 0 && ni < board.length && nj >= 0 && nj < board[0].length) {
                board[i][j] = '#'; // 标记为已访问
                dfs(node, ni, nj, str);
                board[i][j] = char; // 恢复原始状态
            }
        });
    };

    // 遍历整个板子
    for (let i = 0; i < board.length; i++) {
        for (let j = 0; j < board[0].length; j++) {
            dfs(root, i, j, '');
        }
    }

    return result;
};

讲解
这个问题通常被称为“单词搜索”或“Boggle”游戏问题的扩展版本,其中目标是找出所有可能的单词。

  1. 构建字典树 (Trie):
    ○ 字典树是一种高效的数据结构,用于存储字符串集合。它允许我们快速检查一个单词是否存在于集合中,以及在搜索过程中逐步检查部分前缀是否有效。
    ○ 对于给定的单词列表 words,遍历每一个单词,并将其添加到字典树中。在字典树的节点上,我们可以标记单词的结束点,这样在搜索过程中可以快速识别出完整的单词。
  2. 深度优先搜索 (DFS):
    ○ 对于二维网格上的每一个单元格,我们执行深度优先搜索来探索所有可能的方向(上、下、左、右),同时构建一个路径字符串。
    ○ 如果在字典树中找到一个完整的单词,则将其添加到结果列表中,并从字典树中删除该单词的结束标记,以避免重复计算相同的单词。
    ○ 在搜索过程中,为了避免重复访问同一个单元格,我们将访问过的单元格标记为特殊字符(如 #),并在搜索完该路径后恢复原状。
  3. 遍历和搜索:
    ○ 遍历整个二维网格,从每个单元格开始执行深度优先搜索,直到找到所有的单词为止。

思路二


function findWords(board, words) {
    const result = new Set(); // 使用 Set 来存储结果,避免重复
    const trie = buildTrie(words); // 构建字典树
    const rows = board.length;
    const cols = board[0].length;

    for (let row = 0; row < rows; row++) {
        for (let col = 0; col < cols; col++) {
            dfs(board, row, col, trie, "", result);
        }
    }

    return Array.from(result); // 将 Set 转换为数组返回
}

function buildTrie(words) {
    const root = {};
    for (const word of words) {
        let node = root;
        for (const char of word) {
            if (!node[char]) {
                node[char] = {};
            }
            node = node[char];
        }
        node.isEnd = true; // 标记单词的结束
    }
    return root;
}

function dfs(board, row, col, trie, path, result) {
    const char = board[row][col];
    if (!trie[char]) return; // 如果当前字符不在字典树中,返回

    path += char; // 更新路径
    trie = trie[char]; // 移动到下一个节点

    if (trie.isEnd) {
        result.add(path); // 找到一个单词,添加到结果中
    }

    // 标记当前单元格为已访问
    const temp = board[row][col];
    board[row][col] = '#'; // 使用特殊字符标记已访问

    // 进行 DFS 搜索相邻的单元格
    const directions = [
        [0, 1], // 右
        [1, 0], // 下
        [0, -1], // 左
        [-1, 0] // 上
    ];

    for (const [dx, dy] of directions) {
        const newRow = row + dx;
        const newCol = col + dy;
        if (newRow >= 0 && newRow < board.length && newCol >= 0 && newCol < board[0].length && board[newRow][newCol] !== '#') {
            dfs(board, newRow, newCol, trie, path, result);
        }
    }

    // 恢复当前单元格的状态
    board[row][col] = temp;
}

讲解

  1. 构建字典树(Trie):buildTrie 函数用于构建一个字典树,以便快速查找单词。
  2. 深度优先搜索(DFS):
    • dfs 函数用于从当前单元格开始进行深度优先搜索,查找可能的单词。
    • 使用一个 path 字符串来存储当前路径的字符。
    • 使用一个 result 集合来存储找到的单词。
  3. 标记已访问的单元格:在 DFS 搜索过程中,将已访问的单元格标记为 ‘#’,以避免重复使用。
  4. 方向数组:使用一个方向数组来表示四个可能的移动方向(上、下、左、右)
  5. 返回结果:最后,将结果集合转换为数组并返回。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2210051.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

crashrpt3 开源项目的Vs 2022 C++20及其以上的编译

1. 首先从github 下载源代码 crashrpt3 2. 用CMake Gui 编译成vs studio 工程文件 2.1 点击 config 按钮 2.2 依次点击 Generate 按钮、Open Project 按钮.之后vs 2022 会打开编译好的sln工程文件 3.全选解决方案里面的所有项目,设置C语言标准,我这里设置是最新C,即启用的是…

Solidity基础语法

Solidity的在线编辑器&#xff1a;https://remix.ethereum.org/ 一、合约结构 1、SPDX许可标识&#xff1a;指定代码的开源许可 2、pragma指令&#xff1a;声明Solidity版本 3、导入语句&#xff1a;引入其他合约或库 4、合约声明&#xff1a;使用contract关键字 5、状态变量&…

【关系模型】关系完整性约束

按照上面的框架我们已经讲了关系数据结构还有关系操作&#xff0c;今天来补充这一章的关系完整性约束 关系完整性约束 完整性约束 完整性约束可以保证数据的一致性和元组的唯一性 实体完整性约束 比如在学生表中&#xff0c;每一个元组都应该是唯一并且元组之间是可以区分…

JavaScript(Web APIs 作用和分类,DOM数是什么,document是什么,根据css选择器来获取DOM元素,修改DOM元素的方式,边量声明)

变量声明 变量声明有三个 var let 和 const建议&#xff1a; const 优先&#xff0c;尽量使用const&#xff0c;原因是&#xff1a; const 语义化更好 很多变量我们声明的时候就知道他不会被更改了&#xff0c;那为什么不用 const呢&#xff1f; 实际开发中也是&#xff0c;…

【unity框架开发8】unity场景Scene的使用, 如何封装一个场景管理器

文章目录 一、场景基本操作1、加载切换场景2、获取场景信息3、激活场景4、场景基本属性获取5、已加载场景个数6、获取场景中所有物体7、创建新场景8、卸载销毁场景 二、使用协程方法来异步加载场景1、AsyncOperation相关的代码应写在一个协同程序中。2、allowSceneActivation加…

AI深湖DeepLate人工智能的数据集格式开源项目

人工智能的数据集格式 文档 • 入门 • API 参考 • 例子 • 博客 • Slack 社区 • Twitter&#xff08;推特&#xff09; 用其他语言阅读这篇文章: English 深湖 Deep Lake Deep Lake 是一种数据集格式&#xff0c;提供简单的 API 以用于创建、存储和协作处理任何规模的…

Spring Security 与 OAuth 2.0 登录实现指南

文章目录 一、项目概述二、环境准备三、创建GitHub OAuth应用四、项目依赖配置五、配置OAuth 2.0六、创建控制器七、创建视图八、运行应用九、用户界面展示十、总结 在现代的Web应用中&#xff0c;安全性是一个不可忽视的因素。OAuth 2.0作为一种流行的授权框架&#xff0c;提供…

浅析主流监控告警系统基本架构和原理

浅析主流监控告警系统基本架构和原理 一&#xff0c;监控系统的作用和目前主流监控系统 1&#xff0c;作用&#xff1a;监控系统一般有以下这几个作用 实时采集监控数据&#xff1a;包括硬件、操作系统、中间件、应用程序等各个维度的数据。实时反馈监控状态&#xff1a;通过…

论文笔记:RelationPrompt :Zero-Shot Relation Triplet Extraction

论文来源: ACL Findings 2022 论文链接:https://arxiv.org/pdf/2203.09101.pdf 论文代码:http://github.com/declare-lab/RelationPrompt 本篇论文是由阿里达摩院自然语言智能实验室于2022年发表的关于零样本关系抽取的顶会论文,本篇博客将记录我在阅读过程中的一些笔记…

AI自动生成PPT解决方案,AI生成PPT-PrensentationGen-Java实现

AI自动生成PPT解决方案&#xff0c;AI生成PPT-PrensentationGen-Java实现。 利用大语言模型生成PPT文件的SpringBoot Web应用&#xff0c;主要功能是自动化创建演示文稿&#xff0c;适用于快速制作演示材料&#xff0c;特色在于其高效的模板处理和文本替换技术。 点击视频观看…

Python入门:如何在Python中优雅地书写多行字符串!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 多行字符串📒📝 什么是多行字符串?📝 三重引号📝 字符串连接📝 反斜杠⚓️ 相关链接 ⚓️📖 介绍 📖 在编程过程中,时常会遇到需要使用多行字符串的场景。例如,在编写长参数、描述文本或代码文档时,多行字符串…

java生成日历数据列表并按日历格式导出到excel

日历格式输出 日历数据列表导出封装日历格式实体类效果 日历数据列表 /**** 封装日历数据* param year 年份* param month 月份*/public List<InspectionDailyStaffPlanCalendarData> selectCalendarDataList(int year,int month,List<InspectionDailyStaffPlan> …

centos7 Oracle 11g rac 静默安装(NFS配置共享存储)

1.环境信息准备 注意&#xff1a; 在配置网络时&#xff0c;Oracle RAC的每个节点必须具有至少两个以上的网卡&#xff0c;一张网卡对外提供网络服务&#xff0c;另一张网卡用于各个节点间的通信和心跳检测等。在配置RAC集群的网卡时&#xff0c;如果节点1的公共接口是eth0&…

随机变量及其分布

定义 1.随机变量是一个从样本空间&#xff08;所有可能结果的集合&#xff09;到实数集的函数。样本空间中的每个结果都对应于随机变量的一个值。随机变量的值可以是离散的&#xff0c;也可以是连续的。随机变量通常用大写字母表示&#xff0c;如 X、Y 或 Z。 2.随机变量和事…

难点:Linux 死机定位(进程虚拟地址空间耗尽)

死机定位(进程虚拟地址空间耗尽) 一、死机现象 内存富裕,但内存申请失败。 死机时打印: 怀疑是: 1、内存碎片原因导致。 2、进程虚拟地址空间耗尽导致。 3、进程资源限制导致。 二、内存碎片分析 1、理论知识:如何分析内存碎片化情况 使用 /proc/buddyinfo: /proc/…

Java-sec-code学习2

Java-Sec-Code学习1-文件上传漏洞 case1 url: http://127.0.0.1:8080/file/any 这是一个典型的上传页面&#xff0c;我们尝试上传一个文件试试看。 直接上传一个jsp文件&#xff0c;发现可以直接上传&#xff0c;非常顺利。这意味这后端和前端都没有对文件类型进行任何限制。…

[旧日谈]关于Qt的刷新事件频率,以及我们在Qt的框架上做实时的绘制操作时我们该关心什么。

[旧日谈]关于Qt的刷新事件频率&#xff0c;以及我们在Qt的框架上做实时的绘制操作时我们该关心什么。 最近在开发的时候&#xff0c;发现一个依赖事件来刷新渲染的控件会导致程序很容易异常和崩溃。 当程序在运行的时候&#xff0c;其实软件本身的负载并不高&#xff0c;所以…

【LeetCode每日一题】——724.寻找数组的中心下标

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目注意】六【题目示例】七【题目提示】八【解题思路】九【时间频度】十【代码实现】十一【提交结果】 一【题目类别】 前缀和 二【题目难度】 简单 三【题目编号】 724.寻找数组的中心下标 四【…

python基础路径的迁移

本人未安装anaconda或pycharm等&#xff0c;仅安装了某个python环境&#xff0c;因此以下方法仅针对基础python环境的迁移&#xff0c;不确保其他软件或插件正常运行 第一步将原python路径的整个文件夹剪切到新的路径下 第二步修改系统环境变量&#xff0c;将原来的python路径…

胤娲科技:AI绘梦师——一键复刻梵高《星空》

想象一下&#xff0c;你手中握有一张梵高的《星空》原图&#xff0c;只需轻轻一点&#xff0c;AI便能化身绘画大师&#xff0c;一步步在画布上重现那璀璨星河。 这不是科幻电影中的桥段&#xff0c;而是华盛顿大学科研团队带来的“Inverse Painting”项目&#xff0c;正悄然改变…