剑指 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
思路: 参考题解:?大佬题解,详细见代码注释
时间复杂度:O(mn),其中 m 为方格的行数, n 为方格的列数。一共有 O(mn) 个状态需要计算,每个状态递推计算的时间复杂度为 O(1),所以总时间复杂度为 O(mn)。
空间复杂度:O(mn),申请dp二维数组
// 参考:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/qing-xi-yi-dong-de-go-shuang-100-jie-fa-lei-si-dao/
func movingCount(m int, n int, k int) int {
dp := make([][]int, m+1)
for i := range dp { // 初始化二维数组
dp[i] = make([]int, n+1)
}
return dfs(m ,n, 0, 0, k, dp)
}
func dfs(m, n, i, j, k int, dp [][]int) int {
if i < 0 || j < 0 || i >=m || j >= n || dp[i][j] == 1 || (sumPos(i)+sumPos(j)) > k { // 越界/行坐标和列坐标的数位之和大于k
return 0
}
dp[i][j] = 1 // 标记(i, j)位置已走过,防止重复走到同一位置
sum := 1 // (i, j) 本身就是1个能到达的格子,所以初始为1
sum += dfs(m, n, i, j+1, k, dp) // 右
sum += dfs(m, n, i, j-1, k, dp) // 左
sum += dfs(m, n, i+1, j, k, dp) // 下
sum += dfs(m, n, i-1, j, k, dp) // 上
return sum
}
// 求所有位之和
func sumPos(n int) int {
sum := 0
for n > 0 {
sum += n % 10
n = n / 10
}
return sum
}
|