leetcode 面试题13. 机器人的运动范围
xxleyi opened this issue · comments
题:
地上有一个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
示例 1:
输入:m = 3, n = 1, k = 0
输出:1
提示:
1 <= n,m <= 100
0 <= k <= 20
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解:
如果有过「广度搜索」经验,这题算比较直接。想要正确解题,需要注意的是处理好细节,保证 bfs 过程中,正确维护队列。
var movingCount = function(m, n, k) {
function carrySum (pair) {
let sum = 0
for (let e of pair) if (e !== ",") sum += +e
return sum
}
function toIJ(e) {
return e.split(',').map(e => +e)
}
function validIJ(i, j) {
return i >= 0 && i < m && j >= 0 && j < n
}
// helper varaiable
let dir = [[-1, 0], [1, 0], [0, -1], [0, 1]]
// initialize loop invariants related variables: head and tail pointer, queue and doneSet
let head = tail = 0
let queue = Array(m * n), doneSet = new Set()
queue[head] = "0,0"
doneSet.add(queue[head])
// bfs by the queue
while (queue[head] != null) {
// update head pointer to maintain loop invariant
let e = queue[head++]
let [i, j] = toIJ(e)
// update tail pointer to maintain loop invariant
for (let [di, dj] of dir) {
let pair = [di + i, dj + j].join(",")
if (!doneSet.has(pair) && validIJ(i + di, j + dj) && carrySum(pair) <= k) {
queue[++tail] = pair
doneSet.add(queue[tail])
}
}
}
// loop termination: head pointer value is our answer, as well as tail or doneSet.size()
console.assert(head == tail && tail == doneSet.size())
return head
};