day14 题目:剑指 Offer 12. 矩阵中的路径、剑指 Offer 13. 机器人的运动范围
知识点:数组、回溯、搜索,难度为中等、中等
学习计划链接:「剑指 Offer」 - 学习计划
题目 | 知识点 | 难度 |
---|---|---|
剑指 Offer 12. 矩阵中的路径 | 数组、回溯、矩阵 | 中等 |
剑指 Offer 13. 机器人的运动范围 | 深度优先搜索、广度优先搜索 | 中等 |
# 剑指 Offer 12. 矩阵中的路径
给定一个 m x n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中 “相邻” 单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
示例 1:
输入: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出: true
示例 2:
输入: board = [["a","b"],["c","d"]], word = "abcd"
输出: false
提示:
1 <= board.length <= 200
1 <= board[i].length <= 200
board
和word
仅由大小写英文字母组成
注意: 本题与主站 79 题相同:https://leetcode-cn.com/problems/word-search/
# 思路
非常典型的深搜典型题,以矩阵中每个符合单词开头的元素作为起点开始搜。
/** | |
* @param {character[][]} board | |
* @param {string} word | |
* @return {boolean} | |
*/ | |
var exist = function(board, word) { | |
function dfs(i, j, idx) { | |
if(idx == word.length) return true // 找到单词了 | |
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length | |
|| board[i][j] == '#' || board[i][j] != word[idx]) | |
return false // 越界或者不匹配 | |
board[i][j] = '#' // 置为 #,避免重复访问 | |
let flag = false | |
if(dfs(i+1, j, idx+1) || dfs(i-1, j, idx+1) | |
|| dfs(i, j+1, idx+1) || dfs(i, j-1, idx+1)) // 四个方向试探 | |
flag = true | |
board[i][j] = word[idx] // 恢复 | |
return flag | |
} | |
for(let i = 0; i < board.length; ++i) { | |
for(let j = 0; j < board[0].length; ++j) { | |
if(board[i][j] === word[0]) | |
if(dfs(i, j, 0)) return true | |
} | |
} | |
return false | |
}; |
# 剑指 Offer 13. 机器人的运动范围
地上有一个 m 行 n 列的方格,从坐标 [0,0]
到坐标 [m-1,n-1]
。一个机器人从坐标 [0, 0]
的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于 k 的格子。例如,当 k 为 18 时,机器人能够进入方格 [35, 37] ,因为 3+5+3+7=18。但它不能进入方格 [35, 38],因为 3+5+3+8=19。请问该机器人能够到达多少个格子?
示例 1:
输入: m = 2, n = 3, k = 1
输出: 3
示例 2:
输入: m = 3, n = 1, k = 0
输出: 1
提示:
1 <= n,m <= 100
0 <= k <= 20
# 思路
广搜,注意搜索方向可以向右和向下就行了
/** | |
* @param {number} m | |
* @param {number} n | |
* @param {number} k | |
* @return {number} | |
*/ | |
var movingCount = function(m, n, k) { | |
function count(x) { | |
if(x == 0) return 0 | |
let sum = 0 | |
while(x) { | |
sum += x%10 | |
x = Math.floor(x/10) | |
} | |
return sum | |
} | |
let dx = [1, 0] | |
let dy = [0, 1] // 下 右 | |
let canVis = new Array(m).fill(0).map(() => new Array(n).fill(false)) | |
let vis = new Array(m).fill(0).map(() => new Array(n).fill(false)) | |
for(let i = 0; i < m; ++i) | |
for(let j = 0; j < n; ++j) | |
canVis[i][j] = (count(i) + count(j)) <= k | |
function judge(i, j) { | |
if(i < 0 || i >= m || j < 0 || j >= n || !canVis[i][j] || vis[i][j]) | |
return false | |
return true | |
} | |
let q = [] | |
let ans = 0 | |
vis[0][0] = true | |
q.push([0, 0]) | |
while(q.length) { | |
let [x, y] = q.shift() | |
++ans | |
for(let i = 0; i < 2; ++i) { | |
let nx = x + dx[i] | |
let ny = y + dy[i] | |
if(judge(nx, ny)) { | |
vis[nx][ny] = true | |
q.push([nx, ny]) | |
} | |
} | |
} | |
return ans | |
}; |