将元素移动到数组末尾

时间:2021-02-16 13:51:19

标签: python arrays

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

<块引用>

给定一个整数数组和一个整数。编写一个函数,将数组中该整数的所有实例移动到数组末尾并返回数组。 该函数应该就地执行此操作,并且不需要维护其他整数的顺序。

例如:

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

是什么导致了第一个代码片段中的超时?

2 个答案:

答案 0 :(得分:2)

您可以将 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]

答案 1 :(得分:1)

您的第一个代码块可能会产生无限循环,因为在某些情况下,循环不会更改任何一个索引。这是因为您的 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 交换,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

而且这个版本比你展示的工作版本更简洁。