LeetCode100之单词搜索(79)--Java

server/2025/1/13 8:43:53/

1.问题描述

        给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。        

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

        示例1

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

        示例2 

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true

        示例3 

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false

        提示

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • board 和 word 仅由大小写英文字母组成

        难度等级

        中等

        题目链接

        单词搜索

2.解题思路

        这道题要我们在一个矩阵中搜索单词,单词必须按照字母的顺序,通过相邻的单元格内的字母构成。

        这道题,在正式开始解题之前,我们可以将一些不可能的情况排除在外。

        首先,如果我们在搜索的时候,如果索引越界了,那肯定是不行的,所以我们可以先解决一个判断索引是否越界的问题,行列索引要大于等于0同时小于行列索引的最大值。

java">    //判断是否越界public boolean isOutOfIndex(int x,int y,int boardX,int boardY){return x >= 0 && y >=0 && x < boardX && y < boardY;}

        接着,如果说我们单词中的某个字母的个数,比题目提供给我们的board里面的个数还多,那肯定是搜索不到这个单词的。比如我们要找"aaa",但是board中只有两个a,那我们肯定也是找不到的。

        所以我们可以先统计一下board中每个字符的个数和word中每个字符的个数,并将它们进行比较,如果出现我们上面提到的情况,直接返回找不到的结果就好了。

java">        //检查board中单个字符的个数是否比word中少,如果少,肯定不存在int[] wordCount = new int[128];int[] boardCount = new int[128];//统计board中的字符个数for(char[] bo : board){for(char c : bo){boardCount[c]++;}}//统计word中的字符个数并进行比较for(char c : word.toCharArray()){wordCount[c]++;//判断board中单个字符的个数是否比word少if(wordCount[c] > boardCount[c]){return false;}}

        然后我们可以通过遍历board,找到word单词的首个字符在board中的位置,然后从这个位置出发进行搜索,看能不能找到完整的一个word单词。值得注意的是,board中同一个字符可能出现多个,所以当某一个位置的字符找不到完成的单词时,不代表其他位置的字符不行,所以要将整个board都找一遍,除非我们已经找到了。

java">        boolean flag = false;//遍历board,找到word的第一个字符for(int i = 0;i < board.length;i++){for(int j = 0;j < board[0].length;j++){if(board[i][j] ==word.charAt(0)){flag = dfs(board,0,i,j,word);//找到了if(flag == true){return flag;}}}}//没找到,返回falsereturn flag;

        接下来,就是我们核心的搜索方法了,这里我们采用递归的深度搜索。我们通过一个索引index来标记我们找打了word中的第几个字符,同时我们还要传入当前搜索的坐标,以及board和word。

java">    public boolean dfs(char[][] board,int index,int x,int y,String word)

        确定了需要用到的参数之后,我们就可以来判断搜索结束的条件了。如果index等于word的长度了,说明我们已经找到了word的最后一个字符,找到了完整的word单词,返回true;如果还没有找到,就可以判断我们搜索的坐标是否越界,也就是我们一开始干的事情,调用那个判断是否越界的方法进行判断,如果越界了,直接返回false。

java">        //判断是否已经找到wordif(index == word.length()){return true;}//判断坐标是否越界if(!isOutOfIndex(x,y,board.length,board[0].length)){return false;}

        确定完坐标没有越界之后,我们就可以正式进行搜索了。判断board当前位置的字符是否为我们要找到第index个字符,如果不是,直接返回false结束这次的搜索。如果是我们要寻找的字符,将board当前位置的字符用一个临时变量存储起来,并将当前位置设置为0,用来标记被成功搜索到了。接着,我们向上下左右相邻单元格进行搜索,只要有其中一个方向走的通,就是可以返回true,完成四个方向的搜索之后,我们要记得将board当前的位置恢复,这就是我们要用临时变量存储起来的原因,避免本次搜索全部失败,但该位置会是其他搜索成功的关键因素的情况。将字符恢复之后,直接返回搜索结果就可以了。

java">        //判断坐标是否越界if(!isOutOfIndex(x,y,board.length,board[0].length)){return false;}//判断当前坐标是否为我们要找的第index个字符if(word.charAt(index) != board[x][y]){return false;}//将当前字符设置为0,标记为已被访问,后面需要将字符恢复char temp = board[x][y];board[x][y] = '0';//递归查找其他方向boolean flag = dfs(board,index+1,x-1,y,word) || dfs(board,index+1,x+1,y,word)||dfs(board,index+1,x,y-1,word)||dfs(board,index+1,x,y+1,word);//将字符恢复,避免影响其他方向的搜索board[x][y] = temp;//返回结果return flag;

        如果我们遍历完整个board数组之后,仍然没有找到,直接返回false没找到即可。

        这道题基本到这就结束了,但是我们还可以做一个小优化,就是在正式遍历board数组之前,我们可以像判断word的最后一个字符在word中出现的个数是否小于word的第一个字符在board中出现的个数,那我们可以将word翻转之后再进行搜索。因为如果word的第一个字符在board中出现的个数多,那我们搜索失败的次数也就会随之增多,因为极大的可能是那么多位置中只有一个是可以搜索成功的。

java">        //word中最后一个字符的个数小于board中word的第一个字符的个数,可以将字符反转减少递归的次数if(wordCount[word.charAt(word.length()-1)] < boardCount[word.charAt(0)]){word = String.valueOf(new StringBuffer(word).reverse());}

3.代码展示

java">class Solution {public boolean exist(char[][] board, String word) {//检查board中单个字符的个数是否比word中少,如果少,肯定不存在int[] wordCount = new int[128];int[] boardCount = new int[128];//统计board中的字符个数for(char[] bo : board){for(char c : bo){boardCount[c]++;}}//统计word中的字符个数并进行比较for(char c : word.toCharArray()){wordCount[c]++;//判断board中单个字符的个数是否比word少if(wordCount[c] > boardCount[c]){return false;}}//word中最后一个字符的个数小于board中word的第一个字符的个数,可以将字符反转减少递归的次数if(wordCount[word.charAt(word.length()-1)] < boardCount[word.charAt(0)]){word = String.valueOf(new StringBuffer(word).reverse());}boolean flag = false;//遍历board,找到word的第一个字符for(int i = 0;i < board.length;i++){for(int j = 0;j < board[0].length;j++){if(board[i][j] ==word.charAt(0)){flag = dfs(board,0,i,j,word);//找到了if(flag == true){return flag;}}}}//没找到,返回falsereturn flag;}public boolean dfs(char[][] board,int index,int x,int y,String word){//判断是否已经找到wordif(index == word.length()){return true;}//判断坐标是否越界if(!isOutOfIndex(x,y,board.length,board[0].length)){return false;}//判断当前坐标是否为我们要找的第index个字符if(word.charAt(index) != board[x][y]){return false;}//将当前字符设置为0,标记为已被访问,后面需要将字符恢复char temp = board[x][y];board[x][y] = '0';//递归查找其他方向boolean flag = dfs(board,index+1,x-1,y,word) || dfs(board,index+1,x+1,y,word)||dfs(board,index+1,x,y-1,word)||dfs(board,index+1,x,y+1,word);//将字符恢复,避免影响其他方向的搜索board[x][y] = temp;//返回结果return flag;}//判断是否越界public boolean isOutOfIndex(int x,int y,int boardX,int boardY){return x >= 0 && y >=0 && x < boardX && y < boardY;}
}

4.总结

        这道题要写出来不难,但是要减少搜索时间还是有一点难度的,统计word的字符个数和board进行比较和将word的字符串翻转的情况,没有做过类似的题的话,应该挺难想到的。好了,这道题就啰嗦到这里,祝大家刷题愉快~


http://www.ppmy.cn/server/157968.html

相关文章

piexl 手机刷装机包,以及使用面具root手机

刷机 1 下载官方的factory完整包 https://developers.google.cn/android/images?hl=zh-cn#taimen 2 选择版本下载(factory完整包,指定手机型号,选择系统) -taimen-rp1a.201005.004.a1-factory-2f5c4987.zip3 解压, win机器线刷执行脚本flash-all.bat bootloader-taimen…

HTML 闪烁动画(Blink Animation)

HTML 闪烁动画&#xff08;Blink Animation&#xff09; 闪烁动画是一种动态效果&#xff0c;使元素周期性地显现和消失&#xff0c;常用于吸引用户注意。以下是如何使用 CSS 和 HTML 创建闪烁动画的详细说明。 1. 基本概念 闪烁动画&#xff1a;通过改变元素的透明度来实现…

网络安全建设方案,信息安全风险评估报告,信息安全检测文档(Word原件完整版)

一、概述 1.1工作方法 1.2评估依据 1.3评估范围 1.4评估方法 1.5基本信息 二、资产分析 2.1 信息资产识别概述 2.2 信息资产识别 三、评估说明 3.1无线网络安全检查项目评估 3.2无线网络与系统安全评估 3.3 ip管理与补丁管理 3.4防火墙 四、威胁细…

Leetcode3298:统计重新排列后包含另一个字符串的子字符串数目 II

题目描述&#xff1a; 给你两个字符串 word1 和 word2 。如果一个字符串 x 重新排列后&#xff0c;word2 是重排字符串的前缀&#xff0c;那么我们称字符串 x 是 合法的 。 请你返回 word1 中 合法子字符串的数目。 注意 &#xff0c;这个问题中的内存限制比其他题目要 小 &…

leetcode 面试经典 150 题:两数之和

链接两数之和题序号1题型数组解题方法1. 哈希表&#xff0c;2. 暴力法难度简单熟练度✅✅✅✅✅ 题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输…

Windows 下Mamba2 / Vim / Vmamba 环境安装问题记录及解决方法终极版(无需绕过triton)

导航 安装教程导航 Mamba 及 Vim 安装问题参看本人博客&#xff1a;Mamba 环境安装踩坑问题汇总及解决方法&#xff08;初版&#xff09;Linux 下Mamba 及 Vim 安装问题参看本人博客&#xff1a;Mamba 环境安装踩坑问题汇总及解决方法&#xff08;重置版&#xff09;Windows …

QT Must be called on Chrome_UIThread; actually called on Unknown Thread.

具体错误 [4448:9040:0109/135034.634:FATAL:render_frame_host_impl.cc(672)] Check failed: ::content::BrowserThread::CurrentlyOn(BrowserThread::UI). Must be called on Chrome_UIThread; actually called on Unknown Thread. Backtrace:QWebEngineUrlSchemeHandler::q…

A2. 大语言模型llama API服务调研

自然语言模型大家听的比较多的是OpenAI,它有聊天(Chat)、补全(Completion)、提取结果信息(Extract Result Information)、模拟聊天(Mock Chat)等功能;还有其它语言模型比如Google公司研发的mBERT (Multilingual BERT)、BERT (Bidirectional Encoder Representations …