题目描述

原题链接

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:
image.png
输入:board = [[“A”,”B”,”C”,”E”],[“S”,”F”,”C”,”S”],[“A”,”D”,”E”,”E”]], word = “ABCCED”
输出:true

示例 2:
image.png
输入:board = [[“A”,”B”,”C”,”E”],[“S”,”F”,”C”,”S”],[“A”,”D”,”E”,”E”]], word = “SEE”
输出:true

示例 3:
image.png
输入: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 仅由大小写英文字母组成

进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?

个人解法

Javascript

回溯

  1. /*
  2. * @lc app=leetcode.cn id=79 lang=javascript
  3. *
  4. * [79] 单词搜索
  5. */
  6. // @lc code=start
  7. const dfs = function (board, i, j, target, m, n, res) {
  8. if (!target.length) {
  9. return true;
  10. }
  11. let str = target[0];
  12. const up = i > 0 ? board[i - 1][j] : null;
  13. const down = i < m - 1 ? board[i + 1][j] : null;
  14. const left = j > 0 ? board[i][j - 1] : null;
  15. const right = j < n - 1 ? board[i][j + 1] : null;
  16. let flag = false;
  17. if (res.indexOf(`${i - 1},${j}`) === -1 && up === str) {
  18. flag = dfs(board, i - 1, j, target.substring(1), m, n, [...res, `${i - 1},${j}`]) || flag;
  19. if (flag) {
  20. return true;
  21. }
  22. }
  23. if (res.indexOf(`${i + 1},${j}`) === -1 && down === str) {
  24. flag = dfs(board, i + 1, j, target.substring(1), m, n, [...res, `${i + 1},${j}`]) || flag;
  25. if (flag) {
  26. return true;
  27. }
  28. }
  29. if (res.indexOf(`${i},${j - 1}`) === -1 && left === str) {
  30. flag = dfs(board, i, j - 1, target.substring(1), m, n, [...res, `${i},${j - 1}`]) || flag;
  31. if (flag) {
  32. return true;
  33. }
  34. }
  35. if (res.indexOf(`${i},${j + 1}`) === -1 && right === str) {
  36. flag = dfs(board, i, j + 1, target.substring(1), m, n, [...res, `${i},${j + 1}`]) || flag;
  37. if (flag) {
  38. return true;
  39. }
  40. }
  41. return flag;
  42. }
  43. /**
  44. * @param {character[][]} board
  45. * @param {string} word
  46. * @return {boolean}
  47. */
  48. var exist = function (board, word) {
  49. const m = board.length;
  50. const n = board[0].length;
  51. const res = [];
  52. const result = [];
  53. for (let i = 0; i < m; i++) {
  54. for (let j = 0; j < n; j++) {
  55. if (board[i][j] === word[0]) {
  56. res.push([i, j]);
  57. }
  58. }
  59. }
  60. const len = res.length;
  61. if (len === 0) {
  62. return false;
  63. }
  64. for (let i = 0; i < len; i++) {
  65. res[i] = dfs(board, res[i][0], res[i][1], word.substring(1), m, n, [`${res[i][0]},${res[i][1]}`]);
  66. if (res[i]) {
  67. return true;
  68. }
  69. }
  70. return res.indexOf(true) > -1;
  71. };
  72. // @lc code=end

Java

回溯

  1. class Solution {
  2. public boolean exist(char[][] board, String word) {
  3. int w=board[0].length,h=board.length;
  4. boolean[][] flag=new boolean[h][w];
  5. for (int i=0;i<h;i++){
  6. for (int j=0;j<w;j++){
  7. boolean result=check(board,word,flag,i,j,0);
  8. if (result==true){
  9. return true;
  10. }
  11. }
  12. }
  13. return false;
  14. }
  15. public boolean check(char[][] board,String word,boolean[][] flag,int i,int j,int k){
  16. //如果当前字符和位置k的目标字符不相等,直接返回false
  17. if (board[i][j]!=word.charAt(k)){
  18. return false;
  19. //如果最后一位字符对应字符也找到了,说明字符串存在,返回true
  20. }else if (k==word.length()-1){
  21. return true;
  22. }
  23. //当前字符和位置k目标字符对应,寻找下一个字符,标记当前字符已访问
  24. flag[i][j]=true;
  25. boolean result=false;
  26. //上下左右
  27. int[][] nums=new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
  28. for (int[] n:nums){
  29. int newI=i+n[0],newJ=j+n[1];
  30. //判断有没有越界
  31. if (newI>=0&&newJ>=0&&newI< board.length&&newJ<board[0].length){
  32. if (flag[newI][newJ]==false){
  33. boolean f=check(board, word, flag, newI, newJ, k+1);
  34. if (f==true){
  35. result=true;
  36. break;
  37. }
  38. }
  39. }
  40. }
  41. //复原当前字符状态,不阻碍下一次寻找
  42. flag[i][j]=false;
  43. return result;
  44. }
  45. }

其他解法

Java

Javascript

DFS优化

  1. /*
  2. * @lc app=leetcode.cn id=79 lang=javascript
  3. *
  4. * [79] 单词搜索
  5. */
  6. // @lc code=start
  7. /**
  8. * @param {character[][]} board
  9. * @param {string} word
  10. * @return {boolean}
  11. */
  12. var exist = function (board, word) {
  13. const h = board.length, w = board[0].length;
  14. const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];
  15. const visited = new Array(h);
  16. for (let i = 0; i < visited.length; ++i) {
  17. visited[i] = new Array(w).fill(false);
  18. }
  19. const check = (i, j, s, k) => {
  20. if (board[i][j] != s.charAt(k)) {
  21. return false;
  22. } else if (k == s.length - 1) {
  23. return true;
  24. }
  25. visited[i][j] = true;
  26. let result = false;
  27. for (const [dx, dy] of directions) {
  28. let newi = i + dx, newj = j + dy;
  29. if (newi >= 0 && newi < h && newj >= 0 && newj < w) {
  30. if (!visited[newi][newj]) {
  31. const flag = check(newi, newj, s, k + 1);
  32. if (flag) {
  33. result = true;
  34. break;
  35. }
  36. }
  37. }
  38. }
  39. visited[i][j] = false;
  40. return result;
  41. }
  42. for (let i = 0; i < h; i++) {
  43. for (let j = 0; j < w; j++) {
  44. const flag = check(i, j, word, 0);
  45. if (flag) {
  46. return true;
  47. }
  48. }
  49. }
  50. return false;
  51. };
  52. // @lc code=end