题目
地上有一个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,他每次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子。请问该机器人能够到达多少个格子?
例:
当k为18时,机器人能够进入(35, 37),因为3+5+3+7=18。但它不能进入放个(35, 38),
因为3+5+3+8=19。
思路
- 回溯法。和题12同样进入一格后递归处理向其上下左右移动的情况,同时用一个二维数组保存处理过的情况记录。
- 时间复杂度:最坏情况,每一格都能到达,O(m*n)
- 空间复杂度:用来保存的历史记录O(m*n),递归深度O(max(m,n))
- 广度优先搜索:从左上角开始,按斜线处理情况。每一步都只考虑向右或者向下移动的情况,因为向上或者向下的情况等于上一步中另外一个解。 详见代码。
- 时间复杂度:O(m*n)
- 空间复杂度:保存当前解情况O(max(m,n))
代码
思路2:时间复杂度O(m,n),空间复杂度O(max(m,n))
def robot_move(row, col, k):
"""
:param row: row of matrix, m
:param col: col of matrix, n
:param k: bit sum limit
:return: num of blocks can reach
"""
def bit_sum(num):
"""
calculate bit sum
:param num: num
:return: bit sum
"""
b_sum = 0
while num:
b_sum += num % 10
num = num // 10
return b_sum
if row < 1 or col < 1:
raise Exception('Invalid Matrix')
to_check = [(0,0)]
next_check = set() # to remove the duplication
block_count = 0
while to_check:
i_cur, j_cur = to_check.pop(0)
block_count += 1
if j_cur + 1 < col and bit_sum(i_cur) + bit_sum(j_cur + 1) <= k:
# move right
next_check.add((i_cur, j_cur+1))
if i_cur + 1 < row and bit_sum(i_cur + 1) + bit_sum(j_cur) <= k:
# move down
next_check.add((i_cur + 1, j_cur))
if not to_check:
to_check.extend(list(next_check))
next_check = set()
return block_count
思考
- 求各位数字之和不知道有没有什么更好的方法,有助于加速。
- 我的解法中利用集合的不重复特点(实际上是一个哈希表)去除重复的解,如果元素很多的时候,当哈希表每次复制扩大会消耗许多时间。
但是实际上每次的to_check都是从右上有序排列到左下角的,是否可以利用这点,直接处理。 - 本题没有跑测试用例,只检测了边界、特殊输入,因为测试用例得自己算很烦,希望这本书以后可以配套测试库。