第八天
今天继续来写搜索与回溯算法的题目。
二十题
剑指 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。请问该机器人能够到达多少个格子?
示例:
输入: m = 2, n = 3, k = 1
输出: 3
提示:
-
1 <= n,m <= 100 -
0 <= k <= 20
思路: 如下图所示:
在题目中有一个需要注意的点,不能进入行坐标和列坐标的数位之和大于k的格子。例如k为18的时候,不能进入(35,37)是因为3+5+3+7=18,是位数之和不是坐标之和,不是35+37。所以我先写了一个函数来进行这一步判断:
function addNum(num:number):number{
if (num === 100) return 1 //提示中说了m和n最大为100
return (num % 10) + (num - (num % 10)) / 10
那么我一开始异想天开地以为只需要遍历m和n让他们不断执行这个函数,能通过的就可以满足题目条件写了这么一段:
function movingCount(m: number, n: number, k: number): number {
let canGoNum = 0
function addNum(num:number):number{
if (num === 100) return 1
return (num % 10) + (num - (num % 10)) / 10
}
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (addNum(i) + addNum(j) <= k) {
canGoNum++
}
}
}
return canGoNum
};
结果碰壁了,我这样写应该相当于一行一行遍历,在每一行中如果遇到符合条件的就让canGoNum加一。但是失败了,结果比我算出来的要小,那么我就理解了是因为有一些点它满足,但是那些点之前有一些点是不满足的也就是无法到达的,机器人不能进行跳跃,所以即便后面的点能够满足,机器人也无法走到。所以还是得真正地让它“走”起来。
function movingCount(m: number, n: number, k: number): number {
function addNum(num:number):number{
if (num === 100) return 1
return (num % 10) + (num - (num % 10)) / 10
}
if (k === 0) return 1
const columnArr: number[] = new Array(n).fill(0)
const mapArr: number[] = new Array(m).fill(columnArr)
let sum = 0
let goOut = false
for (let i = 0; i < m; i++) {
if (goOut) break
for (let j = 0; j < n; j++) {
if (addNum(i) + addNum(j) <= k) {
mapArr[i][j] = 1
console.log({ i, j })
sum++
} else {
if (j === 0) {
goOut = true
}
break
}
}
}
return sum
};
本以为这样可以解决,结果结果原来他在特殊的地方时会有连接的,于是只能去看了解析。
虽然写了很久还是失败了,很心累,但是还是要把它写出来!所以决定用深度优先算法去写:
function movingCount(m: number, n: number, k: number): number {
function addNum(num:number):number{
if (num === 100) return 1
return (num % 10) + (num - (num % 10)) / 10
}
if (k === 0) return 1
const alreadyGo = [{one:0,two:0}]
let sum = 1
const dfs = (line:number,column:number)=>{
const filterArr = []
if(line+1<m){
if(addNum(line+1)+addNum(column)<=k){
filterArr.push({one:line+1,two:column})
}
}
if(column+1<n){
if(addNum(line)+addNum(column+1)<=k){
filterArr.push({one:line,two:column+1})
}
}
if(line-1>=0){
if(addNum(line-1)+addNum(column)<=k){
filterArr.push({one:line-1,two:column})
}
}
if(column-1>=0){
if(addNum(line)+addNum(column-1)<=k){
filterArr.push({one:line,two:column-1})
}
}
console.log({filterArr});
filterArr.forEach((item)=>{
if(!alreadyGo.includes(item)){
alreadyGo.push(item)
sum++
dfs(item.one,item.two)
}
})
}
dfs(0,0)
return sum
};
写着发现不太对劲。这题写了太多天,明天复习深度优先和广度优先的基础题型。