leetcode中等难度题 -- 18.单词搜索

问题描述:

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

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

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

解题思路:回溯

  1. 定义一个二维数组visited,记录已访问的点,如果下次还能访问这个点,直接返回false。
  2. 定义一个函数,表示基于当前点,是否可以找到剩余字符。
// canFindRest 表示:基于当前选择的点[row,col],能否找到剩余字符的路径。
const canFindRest =
      canFind(row + 1, col, i + 1) ||
      canFind(row - 1, col, i + 1) ||
      canFind(row, col + 1, i + 1) ||
      canFind(row, col - 1, i + 1)

    3. 递归出口:指针越界。在递归中列出所有false的情况。指针越界,表示已经考察完所有字符,没有出现false的情况。

代码实现(js) 

/**
 * @param {character[][]} board
 * @param {string} word
 * @return {boolean}
 */
const exist = (board, word) => {
    const m = board.length;
    const n = board[0].length;
    const used = new Array(m);    // 二维矩阵used,存放bool值
    for (let i = 0; i < m; i++) {
        used[i] = new Array(n);
    }
    // canFind 判断当前点是否是目标路径上的点
    const canFind = (row, col, i) => { // row col 当前点的坐标,i当前考察的word字符索引
        if (i == word.length) {        // 递归的出口 i越界了就返回true
            return true;
        }
        if (row < 0 || row >= m || col < 0 || col >= n) { // 当前点越界 返回false
            return false;
        }
        if (used[row][col] || board[row][col] != word[i]) { // 当前点已经访问过,或,非目标点
            return false;
        }
        // 排除掉所有false的情况,当前点暂时没毛病,可以继续递归考察
        used[row][col] = true;  // 记录一下当前点被访问了
        // canFindRest:基于当前选择的点[row,col],能否找到剩余字符的路径。
        const canFindRest = canFind(row + 1, col, i + 1) || canFind(row - 1, col, i + 1) ||
            canFind(row, col + 1, i + 1) || canFind(row, col - 1, i + 1); 

        if (canFindRest) { // 基于当前点[row,col],可以为剩下的字符找到路径
            return true;    
        }
        used[row][col] = false; // 不能为剩下字符找到路径,返回false,撤销当前点的访问状态
        return false;
    };

    for (let i = 0; i < m; i++) { // 遍历找起点,作为递归入口
      for (let j = 0; j < n; j++) {
        if (board[i][j] == word[0] && canFind(i, j, 0)) { // 找到起点且递归结果为真,找到目标路径
          return true; 
        }
      }
    }
    return false; // 怎么样都没有返回true,则返回false
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值