题目描述
力扣团队买了一个可编程机器人,机器人初始位置在原点(0, 0)。小伙伴事先给机器人输入一串指令command,机器人就会无限循环这条指令的步骤进行移动。指令有两种:
U: 向y轴正方向移动一格
R: 向x轴正方向移动一格。
不幸的是,在 xy 平面上还有一些障碍物,他们的坐标用obstacles表示。机器人一旦碰到障碍物就会被损毁。
给定终点坐标(x, y),返回机器人能否完好地到达终点。如果能,返回true;否则返回false。
示例 1:
输入:command = "URR", obstacles = [], x = 3, y = 2
输出:true
解释:U(0, 1) -> R(1, 1) -> R(2, 1) -> U(2, 2) -> R(3, 2)。
示例 2:
输入:command = "URR", obstacles = [[2, 2]], x = 3, y = 2
输出:false
解释:机器人在到达终点前会碰到(2, 2)的障碍物。
示例 3:
输入:command = "URR", obstacles = [[4, 2]], x = 3, y = 2
输出:true
解释:到达终点后,再碰到障碍物也不影响返回结果。
解题思路
拿到这道题首先可以模拟这个过程,用取模运算来模拟循环过程,可是很不幸超时了,超时代码也贴出来吧:
class Solution(object):
def robot(self, command, obstacles, x, y):
m = len(command)
p = 0; q= 0; i = 0
while True:
chr = i % m
if command[chr] == 'U':
q += 1
else:
p += 1
if [p, q] in obstacles:
return False
i += 1
if p == x and q == y:
return True
elif q > y or p > x:
return False
S = Solution()
print(S.robot("URR", [], 3, 2))
于是换一个思路来,可以通过字典来存储第一个循环内所有可能的点,然后记录最后一个点的横纵坐标。然后判断障碍物是否在路线上,给定一个障碍物坐标,可以把其映射到第一轮循环的坐标中,终点坐标也是。这里以一个例子举例:
这里假设指令为"RRRUUU",那么一轮循环就是从(0,0)到(3,3),保存字典中就是{0: [1], 1: [0], 2: [0], 3: [0, 1, 2, 3]},并且保存终点的横纵坐标,这里横坐标r = 3, 纵坐标u = 3,假设对于一个障碍物点(4, 3),判断其是否在路线上,可以计算times = 4//3 =1,然后4 - times* r = 1, 3 - times * u = 0,所以将(4, 3)映射到(1, 0)上,再判断(1, 0)是否再字典中。
对于障碍(3, 0),计算得3//3 = 1,然后3 - 1 * 3 = 0,0 - 1 * 3 = -3, 这里就需要再判断一次,如果变换后得横坐标为0并且纵坐标小于1,就执行变回运算,即横坐标加r,纵坐标加u
from collections import defaultdict
class Solution(object):
def robot(self, command, obstacles, x, y):
xy = defaultdict(list)
r = u = 0
xy[0].append(0)
for c in command:
if c == 'R':
r += 1
else:
u += 1
xy[r].append(u)
def onThePath(temp):
if temp[0] > x or temp[1] > y:
return False
times, a = divmod(temp[0], r)
p = temp[0] - times * r
q = temp[1] - times * u
if p == 0 and q < 0:
p += r; q += u
if q in xy[p]:
return True
else:
return False
for obtacle in obstacles:
if onThePath(obtacle):
return False
return True if onThePath([x, y]) else False
S = Solution()
print(S.robot("RUUR", [[10, 5], [1, 6], [6, 10], [3, 0], [0, 3], [0, 10], [6, 2]], 7856, 9033))