剑指 Offer 13. 机器人的运动范围

109 阅读2分钟

题目描述

地上有一个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

解题思路1: DFS

使用DFS 构造一个set, 记录遍历过的(i,j), 从左上角(0, 0) 往右下DFS, 然后进行边界判断以及题目规则判断
这里虽然机器人可以上下左右走, 但是我们依然可以只进行右下两个方向是因为左上的位置我们一定是已经遍历过的, 就不用遍历了

示例代码1:

def movingCount(m: int, n: int, k: int) -> int:
    def dfs(i, j):
        if not 0 <= i < m or not 0 <= j < n or sums(i) + sums(j) > k or (i, j) in visit:
            return 0
        visit.add((i, j))
        return 1 + dfs(i + 1, j) + dfs(i, j + 1)

    def sums(x): # 题目规则判断的辅助函数
        s = 0
        while x != 0:
            s += x % 10
            x = x // 10
        return s

    visit = set()
    return dfs(0, 0)

解题思路2: BFS

使用BFS 构造一个queue, 首先将(0, 0)进队, 然后进行queue的遍历, 对于queue的每个元素, 判断他右边和下边的元素是否复合题目规则(越界或数位和)
如果符合规则就将元素进队. 将当前元素加入结果的set中, 最终set的长度就是最终结果

示例代码2:

def movingCount(m: int, n: int, k: int) -> int:
    def sums(x):
        s = 0
        while x != 0:
            s += x % 10
            x = x // 10
        return s

    queue = [(0, 0)]
    visit = set()

    while queue:
        i, j = queue.pop(0)
        if i >= m or j >= n or sums(i) + sums(j) > k:
            continue

        visit.add((i, j))
        queue.append((i + 1, j))
        queue.append((i, j + 1))

    return len(visit)