【问题标题】:Move element to end of array将元素移动到数组末尾
【发布时间】:2021-02-16 13:51:19
【问题描述】:

我有以下问题(来自 AlgoExpert):

给你一个整数数组和一个整数。编写一个函数,将数组中该整数的所有实例移动到数组末尾并返回数组。 该函数应该执行这个 IN-PLACE 并且不需要维护其他整数的顺序。

例如:

array = [2,1,2,2,2,3,4,2]
toMove = 2

Expected = [1,3,4,2,2,2,2,2] 
           (the numbers 1,3,4 could be ordered differently)

我的代码:

def moveElementToEnd(array, toMove):
    l = 0
    r = len(array) - 1
    while l < r:
        if array[l] == toMove and array[r] == toMove:
            r -= 1
        elif array[l] != toMove and array[r] != toMove:
            l += 1
        elif array[l] == toMove and array[r] != toMove:
            array[l], array[r] = array[r], array[l]
            l += 1
            r -= 1
    return array

这会超时,但是当我如下更改 if 语句时,它可以正常工作:

def moveElementToEnd(array, toMove):
    if len(array) < 1:
        return array
    l = 0
    r = len(array) - 1
    while l < r:
        if array[l] == toMove and array[r] != toMove:
            array[l], array[r] = array[r], array[l]
            l += 1
            r -= 1      
        elif array[l] != toMove and array[r] != toMove:
            l += 1
        else:
            r -= 1
    return array

第一个代码sn-p超时是什么原因?

【问题讨论】:

    标签: python arrays


    【解决方案1】:

    您可以将sort 与自定义key 一起使用,将每个元素与toMove 进行比较。所有False 值将在左侧,所有True 值将在右侧。因此,所有toMove 值都将位于列表的最后。

    >>> array = [2,1,2,2,2,3,4,2]
    >>> toMove = 2
    >>> array.sort(key=lambda i: i == toMove)
    >>> array
    [1, 3, 4, 2, 2, 2, 2, 2]
    

    【讨论】:

      【解决方案2】:

      您的第一个代码块可能会产生无限循环,因为在某些情况下循环不会更改任何一个索引。这是因为您的 if ..elif.. 构造最后没有包罗万象(使用 else

      原来这部分有问题:

              if array[l] == toMove and array[r] == toMove:
                  r -= 1
              elif array[l] != toMove and array[r] != toMove:
                  l += 1
              elif array[l] == toMove and array[r] != toMove:
                  array[l], array[r] = array[r], array[l]
                  l += 1
                  r -= 1
      

      array[l] != toMovearray[r] == toMove 什么都不做,所以循环会无限运行。

      您可以将四种可能性想象如下:

      array[r] == toMove array[r] != toMove
      array[l] == toMove 1 2
      array[l] != toMove 3 4

      您的错误代码处理案例 1、4 和 2(按此顺序),但不处理案例 3

      工作代码首先处理情况 2 和 4,在最后的else 中它同时处理情况 1 和 3。

      你希望在这四种情况下发生的事情是:

      array[r] == toMove array[r] != toMove
      array[l] == toMove r-=1 swap, l+=1; r-=1
      array[l] != toMove r-=1 l+=1

      因此,您的代码的修复方法是更改​​此:

      if array[l] == toMove and array[r] == toMove: 
      

      到这里:

      if array[r] == toMove: 
      

      所以它一次处理两个案例。

      通过这种更改,第二个条件可以简化:如果执行到达那里,我们知道array[r] != toMove,因此不需要对其进行测试。也不再需要第二个elif 条件,因为只要执行到达那里,该条件就会为真。您可以将其更改为else

          if array[r] == toMove:
              r -= 1
          elif array[l] != toMove:
              l += 1
          else:
              array[l], array[r] = array[r], array[l]
              l += 1
              r -= 1
      

      而且这个版本比你提供的工作版本更简洁。

      【讨论】:

      • 这就是为什么在 if-elif 语句的末尾不写 else 是不好的做法的主要原因?
      • 我仍然不确定为什么在第二个代码块上我确实捕捉到了所有场景
      • @nomno 通常使用else 并不是“坏习惯”。而在 您当前的代码 中,您的逻辑存在缺陷。这是两种不同的说法。
      • 我在回答中添加了更多分析。
      • 感谢您的详尽回答!
      猜你喜欢
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      • 2021-09-11
      • 1970-01-01
      • 2023-03-17
      相关资源
      最近更新 更多