LeetCode 剑指Offer 13 机器人的运动范围
题目
解题
深度优先和广度优先解题思路参考:
剑指 Offer 13. 机器人的运动范围( 回溯算法,DFS / BFS ,清晰图解)
解题一:深度优先搜索
// javascript
var movingCount = function(m, n, k) {
const movingSteps = (i, j) => {
visited[i][j] = true;
// 如果 (get(i) + get(j)) > k,无法进入当前格子,无法再向当前格子的四周搜索
if ((get(i) + get(j)) <= k) {
cnt++;
for (const [movei, movej] of directions) {
const newi = i + movei, newj = j + movej;
if (newi >= 0 && newi < m && newj >= 0 && newj < n && !visited[newi][newj]) {
movingSteps(newi, newj);
}
}
}
}
let cnt = 0;
const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]];
const visited = new Array(m).fill(false).map(() => new Array(n).fill(false));
movingSteps(0, 0);
return cnt;
};
const get = (i) => {
let sum = 0;
while (i > 0) {
sum += (i % 10);
i = Math.floor(i / 10);
}
return sum;
};
// javascript
var movingCount = function(m, n, k) {
const dfs = (i, j, sumi, sumj) => {
// 只会向左或向下,所以 i 和 j 必定大于等于 0
if (i >= m || j >= n || visited[i][j] || (sumi + sumj) > k) return 0;
visited[i][j] = true;
const moveDownCnt = dfs(i + 1, j, (i + 1) % 10 ? sumi + 1 : sumi - 8, sumj);
const moveRightCnt = dfs(i, j + 1, sumi, (j + 1) % 10 ? sumj + 1 : sumj - 8);
return 1 + moveDownCnt + moveRightCnt;
}
const visited = new Array(m).fill(false).map(() => new Array(n).fill(false));
return dfs(0, 0, 0, 0);
};
解题二:广度优先搜索
// javascript
var movingCount = function(m, n, k) {
const queue = new Array();
const visited = new Array(m).fill(false).map(() => new Array(n).fill(false));
queue.push([0, 0]);
let cnt = 0;
while (queue.length > 0) {
const [i, j] = queue.shift();
if (i >= m || j >= n || visited[i][j] || get(i) + get(j) > k) continue;
visited[i][j] = true;
cnt += 1;
queue.push([i + 1, j]);
queue.push([i, j + 1]);
}
return cnt;
};
const get = (i) => {
let sum = 0;
while (i > 0) {
sum += (i % 10);
i = Math.floor(i / 10);
}
return sum;
};
解题三:动态规划
// javascript
var movingCount = function(m, n, k) {
const visited = new Array(m).fill(false).map(() => new Array(n).fill(false));
// 起始位置一定能到达,cnt 初始化为 1,visited[0][0] 设为 true
let cnt = 1;
visited[0][0] = true;
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
if ((i === 0 && j === 0) || (get(i) + get(j)) > k) continue;
// 如果左边或者上面有格子,看是否为 true:只有左边或上面的格子可以走到当前格子
// 否则尽管坐标和满足条件,但是无法连通
visited[i][j] = (i >= 1 && visited[i - 1][j]) || (j >= 1 && visited[i][j - 1]);
cnt += visited[i][j];
}
}
return cnt;
};
const get = (i) => {
let sum = 0;
while (i > 0) {
sum += (i % 10);
i = Math.floor(i / 10);
}
return sum;
};