Leetcode-机器人大冒险 (python)

题目

力扣团队买了一个可编程机器人,机器人初始位置在原点(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), 而障碍点在(42))
            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!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值