Leetcode-机器人大冒险
题目
力扣团队买了一个可编程机器人,机器人初始位置在原点(0, 0)。小伙伴事先给机器人输入一串指令command,机器人就会**无限循环(这里一开始没看到)**这条指令的步骤进行移动。指令有两种:
U: 向y轴正方向移动一格
R: 向x轴正方向移动一格。
不幸的是,在 xy 平面上还有一些障碍物,他们的坐标用obstacles表示。机器人一旦碰到障碍物就会被损毁。
给定终点坐标(x, y),返回机器人能否完好地到达终点。如果能,返回true;否则返回false。
限制:(一定要注意看限制)
2 <= command的长度 <= 1000
2.command由U,R构成,且至少有一个U,至少有一个R
0 <= x <= 1e9, 0 <= y <= 1e9 (这里说明终点可能很大,超时的可能性很大)
0 <= obstacles的长度 <= 1000
obstacles[i]不为原点或者终点
示例 1:
输入:command = “URR”, obstacles = [], x = 3, y = 2
输出:true
解释:U(0, 1) -> R(1, 1) -> R(2, 1) -> U(2, 2) -> R(3, 2)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/programmable-robot
暴力法
方法直观,但是会超时。
class Solution(object):
def robot(self, command, obstacles, x, y):
"""
:type command: str
:type obstacles: List[List[int]]
:type x: int
:type y: int
:rtype: bool
"""
x0, y0 = 0, 0
i = 0
# 按照指示的步骤,每次走一步, 判断两点:
while(x0<=x and y0<=y):
# decide the direction
if command[i%len(command)]=="U":
y0 += 1
elif command[i%len(command)]=="R":
x0 += 1
else:
return False
# 1. 当前坐标点是不是有阻碍
if [x0, y0] in obstacles:
return False
# 2. 是否达到终点了
if x0 == x and y0 == y:
return True
i += 1
return False
优化方法:减少时间
返回True的两个条件:
1.终点在路径中
2.障碍点不在路径中
因此判断两个问题:
1.终点是不是在路径中
2.障碍点是不是在路径中
只要是按照command走一遍,在x方向和y方向的运动距离就是固定的,既然每一轮迭代向终点靠近的距离是固定的,那么先计算至少需要完整遍历command多少轮,然后从终点减去这个距离, 然后只在最后一轮进行判断。对于障碍点,也是同一个判断原理
判断方法相同
class Solution(object):
def robot(self, command, obstacles, x, y):
"""
:type command: str
:type obstacles: List[List[int]]
:type x: int
:type y: int
:rtype: bool
"""
# 终点是否在路径中: 希望在
flag1 = self.isInPath(command, x, y)
# 每一个障碍点是否在路径中: 希望不在
flag2 = True
for xt, yt in obstacles:
# 当障碍点大于终点的时候则肯定不在,所以先排除掉
#(例如终点为(3.2), 而障碍点在(4,2))
if xt<=x and yt<=y:
if self.isInPath(command, xt, yt):
flag2 = False
return (flag1 and flag2)
# 判断一个点(x, y)是否会出现在路径中
def isInPath(self,command, x, y):
# 统计走一轮command后,在x和y方向可以移动的步长
xx, yy = 0, 0
for i in command:
if i=="U":
yy += 1
elif i == "R":
xx += 1
# 由于此时可能command的指令可能全往一个方向移动,就会出现除数为0情况
# 使用if...elif...进行排除
if xx!=0 and yy!=0:
circle = min(x//xx, y//yy)
elif xx!=0 and yy==0:
circle = x//xx
elif xx==0 and yy!=0:
circle = y/yy
else:
circle = 0
# 当前目标终点减去需要完整迭代的轮数
x = x-circle*xx
y = y-circle*yy
# 按照commond,走最后一遍,看是否经过终点
x0, y0 = 0, 0
i = 0
while (1):
# 由于可能出现(x,y)=(0,0), 此时最后一轮不需要遍历,所以先判断
if x0==x and y0==y:
return True
if command[i%len(command)]=="U":
y0 += 1
if command[i%len(command)]=="R":
x0 += 1
# 当走的距离在某个轴上已经大于终点了,还没有遇到终点,那说明不在路径中了
if x0>x or y0>y:
return False
i += 1
时间复杂度和空间复杂度分析
1.暴力法:时间复杂度为O(n), 空间复杂度为O(1);其中n最大为到终点的x轴和y轴的总的步数
2.优化方法:时间复杂度为O(a*b), 空间复杂度为O(1);a 为障碍物的数量, b为command的长度,最坏的情况是对每个障碍物都要进行判断
今天是2020年的第一天,有一个还不错的开始,keep going!