美文网首页
39.LeetCode874. 模拟行走机器人

39.LeetCode874. 模拟行走机器人

作者: 月牙眼的楼下小黑 | 来源:发表于2018-10-06 11:12 被阅读140次
    • 标签: 贪心
    • 难度: 简单

    • 题目描述
    • 解法1 : 超时版本 1

    收到 转向指令,则更新当前朝向;收到 移动指令 时,根据不同朝向调整位置坐标:首先判断 前方 最近障碍物的位置,如果最近距离大于移动指令给定的距离,则前进移动指令的距离,否则只能前进到最近障碍物的前一个网格方块上。

    注意一个坑: 返回结果是执行指令过程中离原点的最大距离,而非执行完后终点位置离原点的距离。明确思路后,不难实现如下代码:

    class Solution(object):
        def robotSim(self, commands, obstacles):
            """
            :type commands: List[int]
            :type obstacles: List[List[int]]
            :rtype: int
            """
            orient = 'N'
            p = [0,0]
            result = 0
            for i, c in enumerate(commands):
                print('---------------------------------\n',i)
                print('c=', c)
                if(c == -2):
                    if(orient == 'N'):
                        orient = 'W'
                    elif(orient == 'E'):
                        orient = 'N'
                    elif(orient == 'S'):
                        orient = 'E'
                    else:
                        orient = 'S'
                
                if(c == -1):
                    if(orient == 'N'):
                        orient = 'E'
                    elif(orient == 'E'):
                        orient = 'S'
                    elif(orient == 'S'):
                        orient = 'W'
                    else:
                        orient = 'N'
                
                if(1<= c <=9):
                    if(orient == 'E'):
                        dis = [ob[0] - p[0] for ob in obstacles if ob[1] == p[1] and ob[0] > p[0] ]
                        if(not dis or min(dis) > c):
                            p[0] += c
                            print('orient:', orient)
                            print('p:',p[0],p[1])
                        else:
                            p[0] +=min(dis)-1
                            print('orient:', orient)
                            print('p:',p[0],p[1])
                            
                    if(orient == 'W'):
                        dis = [p[0] - ob[0] for ob in obstacles if ob[1] == p[1] and ob[0] < p[0] ]
                        if(not dis or min(dis) > c):
                            p[0] -= c
                            print('orient:', orient)
                            print('p:',p[0],p[1])
                        else:
                            p[0] -= min(dis) -1
                            print('orient:', orient)
                            print('p:',p[0],p[1])
                    
                    if(orient == 'N'):
                        dis = [ob[1] - p[1] for ob in obstacles if ob[0] == p[0] and ob[1] > p[1] ]
                        if(not dis or min(dis) > c):
                            p[1] += c
                            print('orient:', orient)
                            print('p:',p[0],p[1])
                        else:
                            p[1] += min(dis) -1
                            print('orient:', orient)
                            print('p:',p[0],p[1])
                            
                    if(orient == 'S'):
                        dis = [p[1] - ob[1] for ob in obstacles if ob[0] == p[0] and ob[1] < p[1] ]
                        if(not dis or min(dis) > c):
                            p[1] -= c
                            print('orient:', orient)
                            print('p:',p[0],p[1])
                        else:
                            p[1] -= min(dis) -1
                            print('orient:', orient)
                            print('p:',p[0],p[1])
                
                result = max(result,p[0]**2 + p[1]**2)
                print('result:',result)
       
            return result
    
    • 解法2: 超时版本2

    解法1 超时了, 判断超时主要由 判断前方最近障碍物 这一步造成的,这一步我有一个 遍历大数组 (即数组 obstacles)的操作。优化方法是:前进一步,查看当前位置是否存在障碍物,即 “走一步,看一步”“, 这是一个大数组查找的操作。可以通过下面的一个小例子来比较 python list 的遍历和查找的效率。

    # list 的查找时间
    in:
    
    from time import time
    a = 100 * np.random.rand(100000)
    a[20] = 3
    a = list(a)
    start = time()
    b = 3 in a
    elapsed = (time() - start)
    print("Time used:",elapsed)
    
    out: Time used: 8.153915405273438e-05
    
    # list 的遍历时间
    in:
    
    from time import time
    a = 100 * np.random.rand(100000)
    a[20] = 3
    a = list(a)
    start = time()
    b = [i for i in a if i >2]
    elapsed = (time() - start)
    print("Time used:",elapsed)
    
    out: Time used: 0.02106785774230957
    
    class Solution(object):
        def robotSim(self, commands, obstacles):
            """
            :type commands: List[int]
            :type obstacles: List[List[int]]
            :rtype: int
            """
            orient = 'N'
            p = [0,0]
            result = 0
            start = time()
            for i, c in enumerate(commands):
                if(c == -2):
                    if(orient == 'N'):
                        orient = 'W'
                    elif(orient == 'E'):
                        orient = 'N'
                    elif(orient == 'S'):
                        orient = 'E'
                    else:
                        orient = 'S'
                
                if(c == -1):
                    if(orient == 'N'):
                        orient = 'E'
                    elif(orient == 'E'):
                        orient = 'S'
                    elif(orient == 'S'):
                        orient = 'W'
                    else:
                        orient = 'N'
                
                if(1<= c <=9):
                    if(orient == 'E'):
                        move = c
                        while(move>0):
                            next_p = [p[0] + 1, p[1]]
                            if next_p not in obstacles:
                                p = next_p
                                move -= 1
                            else:
                                break
                                  
                    if(orient == 'W'):
                        move = c
                        while(move>0):
                            next_p = [p[0] - 1, p[1]]
                            if next_p not in obstacles:
                                p = next_p
                                move -= 1
                            else:
                                break
                        
                    if(orient == 'N'):
                        move = c
                        while(move>0):
                            next_p = [p[0], p[1] + 1]
                            if next_p not in obstacles:
                                p = next_p
                                move -= 1
                            else:
                                break
                            
                    if(orient == 'S'):
                        move = c
                        while(move>0):
                            next_p = [p[0], p[1] - 1]
                            if next_p not in obstacles:
                                p = next_p
                                move -= 1
                            else:
                                break
                
                result = max(result,p[0]**2 + p[1]**2)
            elapsed = (time() - start)
            print("Time used:",elapsed)
       
            return result
    
    • 解法3 :AC 版本

    很遗憾,解法 2 也超时了,无法从算法角度进行进一步优化了。只能去看看 discussion, 发现 Python 中 不同数据结构的查找效率具有显著差异,可以通过 【CSDN: Python 中list ,set,dict的大规模查找效率】 中的一个例子获得直观感受, 查找效率对比: set>dict>list

    in:
    
    import numpy
    import  time
    l=[]
    sl=set()
    dl=dict()
    r=numpy.random.randint(0,10000000,100000)
    for i in range(0,100000):
        l.append(r[i])
        sl.add(r[i])
        dl.setdefault(r[i],1)
        
    #生成3种数据结构供查找,常规的list,集合sl,字典dl.里面的元素都是随机生成的,
    #为什么要随机生成元素?这是防止某些结构对有序数据的偏向导致测试效果不客观。
    
    start=time.clock()
    for i in range(100000):
        t=i in sl
    end=time.clock()
    print("set:",end-start)
    #计算通过set来查找的效率
    start=time.clock()
    for i in range(100000):
        t=i in dl
    end=time.clock()
    print("dict:",end-start)
    #计算通过dict的效率
    start=time.clock()
    for i in range(100000):
        t=i in l
    end=time.clock()
    print('list:', end-start) # 时间过长(>10 min )
    
    
    out:
    
    set: 0.008858999999972639
    dict: 0.011525000000006003
    ---------------------------------------------------------------------------
    KeyboardInterrupt                         Traceback (most recent call last)
    <ipython-input-25-f68b2e8e02d4> in <module>()
         27 start=time.clock()
         28 for i in range(100000):
    ---> 29     t=i in l
         30 end=time.clock()
         31 print('list:', end-start) # 时间过长(>10 min )
    
    KeyboardInterrupt: 
    
    class Solution(object):
        def robotSim(self, commands, obstacles):
            """
            :type commands: List[int]
            :type obstacles: List[List[int]]
            :rtype: int
            """
            orient = 'N'
            p = [0,0]
            result = 0
            obstacles = set(map(tuple, obstacles))
            start = time()
            for i, c in enumerate(commands):
                if(c == -2):
                    if(orient == 'N'):
                        orient = 'W'
                    elif(orient == 'E'):
                        orient = 'N'
                    elif(orient == 'S'):
                        orient = 'E'
                    else:
                        orient = 'S'
                
                if(c == -1):
                    if(orient == 'N'):
                        orient = 'E'
                    elif(orient == 'E'):
                        orient = 'S'
                    elif(orient == 'S'):
                        orient = 'W'
                    else:
                        orient = 'N'
                
                if(1<= c <=9):
                    if(orient == 'E'):
                        move = c
                        while(move>0):
                            next_p = (p[0] + 1, p[1])
                            if next_p not in obstacles:
                                p = next_p
                                move -= 1
                            else:
                                break
                                  
                    if(orient == 'W'):
                        move = c
                        while(move>0):
                            next_p = (p[0] - 1, p[1])
                            if next_p not in obstacles:
                                p = next_p
                                move -= 1
                            else:
                                break
                        
                    if(orient == 'N'):
                        move = c
                        while(move>0):
                            next_p = (p[0], p[1] + 1)
                            if next_p not in obstacles:
                                p = next_p
                                move -= 1
                            else:
                                break
                            
                    if(orient == 'S'):
                        move = c
                        while(move>0):
                            next_p = (p[0], p[1] - 1)
                            if next_p not in obstacles:
                                p = next_p
                                move -= 1
                            else:
                                break
                
                result = max(result,p[0]**2 + p[1]**2)
            elapsed = (time() - start)
            print("Time used:",elapsed)
       
            return result
    
    • 其他解法*

    暂略。

    相关文章

      网友评论

          本文标题:39.LeetCode874. 模拟行走机器人

          本文链接:https://www.haomeiwen.com/subject/lrthaftx.html