简体   繁体   English

将零移到列表末尾

[英]Move zeroes to end of list

I am working on moving all zeroes to end of list.我正在努力将所有零移到列表末尾。 .. is this approach bad and computationally expensive? ..这种方法是否糟糕且计算成本高?

a = [1, 2, 0, 0, 0, 3, 6]
temp = []
zeros = []

for i in range(len(a)):
    if a[i] !=0:
        temp.append(a[i])
    else:
        zeros.append(a[i])

print(temp+zeros)

My Program works but not sure if this is a good approach?我的程序有效,但不确定这是否是一个好方法?

A sorted solution that avoids changing the order of the other elements is:避免更改其他元素顺序的sorted解决方案是:

from operator import not_

sorted(a, key=not_)

or without an import:或没有导入:

sorted(a, key=lambda x: not x)  # Or x == 0 for specific numeric test

By making the key a simple boolean, sorted splits it into things that are truthy followed by things that are falsy, and since it's a stable sort, the order of things within each category is the same as the original input.通过使键成为一个简单的布尔值, sorted将其分为真值和假值,并且由于它是一种稳定的排序,每个类别中的事物的顺序与原始输入相同。

This looks like a list.这看起来像一个列表。 Could you just use sort?你可以只使用排序吗?

a = [1, 2, 0, 0, 0, 3, 6]
a.sort(reverse=True)
a

[6, 3, 2, 1, 0, 0, 0]

To move all the zeroes to the end of the list while preserving the order of all the elements in one traversal, we can keep the count of all the non-zero elements from the beginning and swap it with the next element when a non-zero element is encountered after zeroes.为了将所有的零移动到列表的末尾,同时在一次遍历中保留所有元素的顺序,我们可以从头开始保留所有非零元素的计数,并在非零元素时将其与下一个元素交换在零之后遇到元素。 This can be explained as:这可以解释为:

arr = [18, 0, 4, 0, 0, 6]
count = 0
for i in range(len(arr):
    if arr[i] != 0:
        arr[i], arr[count] = arr[count], arr[i]
        count += 1

How the loop works:循环的工作原理:

when i = 0, arr[i] will be 18, so according to the code it will swap with itself, which doesn't make a difference, and count will be incremented by one.当 i = 0 时, arr[i] 将是 18,因此根据代码它将与自身交换,这没有区别,并且 count 将增加 1。 When i=1, it will have no affect as till now the list we have traversed is what we want(zero in the end).当 i=1 时,它不会有任何影响,因为到目前为止我们遍历的列表是我们想要的(最后为零)。 When i=4, arr[i]= 4 and arr[count(1)]= 0, so we swap them leaving the list as[18, 4, 0, 0, 0, 6] and count becomes 2 signifying two non-zero elements in the beginning.当 i=4 时,arr[i]= 4 和 arr[count(1)]= 0,所以我们交换它们离开列表为 [18, 4, 0, 0, 0, 6] 并且 count 变为 2 表示两个非- 开头的零元素。 And then the loop continues.然后循环继续。

Nothing wrong with your approach, really depends on how you want to store the resulting values.您的方法没有任何问题,实际上取决于您希望如何存储结果值。 Here is a way to do it using list.extend() and list.count() that preserves order of the non-zero elements and results in a single list.这是一种使用list.extend()list.count() ,它保留非零元素的顺序并生成单个列表。

a = [1, 2, 0, 0, 0, 3, 6]

result = [n for n in a if n != 0]
result.extend([0] * a.count(0))
print(result)
# [1, 2, 3, 6, 0, 0, 0]

There's nothing wrong with your solution, and you should always pick a solution you understand over a 'clever' one you don't if you have to look after it.你的解决方案没有任何问题,如果你必须照顾它,你应该总是选择一个你理解的解决方案而不是一个你不知道的“聪明”的解决方案。

Here's an alternative which never makes a new list and only passes through the list once.这是一个从不创建新列表而只通过列表一次的替代方法。 It will also preserve the order of the items.它还将保留项目的顺序。 If that's not necessary the reverse sort solution is miles better.如果这不是必需的,反向排序解决方案会更好。

def zeros_to_the_back(values):
    zeros = 0
    for value in values:
        if value == 0:
            zeros += 1
        else:
            yield value

    yield from (0 for _ in range(zeros))

print(list(
    zeros_to_the_back([1, 2, 0, 0, 0, 3, 6])
))

# [1, 2, 3, 6, 0, 0, 0]

This works using a generator which spits out answers one at a time.这使用一个生成器一次输出一个答案。 If we spot a good value we return it immediately, otherwise we just count the zeros and then return a bunch of them at the end.如果我们发现一个好的值,我们会立即返回它,否则我们只计算零,然后在最后返回一堆零。

yield from is Python 3 specific, so if you are using 2, just can replace this with a loop yielding zero over and over. yield from是特定yield from Python 3 的,所以如果您使用的是 2,只需将其替换为一次又一次产生零的循环。

You can try this你可以试试这个

a = [1, 2, 0, 0, 0, 3, 6]
x=[i for i in a if i!=0]
y=[i for i in a if i==0]
x.extend(y)
print(x)

Numpy solution that preserves the order保留顺序的 Numpy 解决方案

import numpy as np

a = np.asarray([1, 2, 0, 0, 0, 3, 6])
# mask is a boolean array that is True where a is equal to 0
mask = (a == 0)
# Take the subset of the array that are zeros
zeros = a[mask]
# Take the subset of the array that are NOT zeros
temp = a[~mask]
# Join the arrays
joint_array = np.concatenate([temp, zeros])

I tried using sorted, which is similar to sort().我尝试使用 sorted,它类似于 sort()。

a = [1, 2, 0, 0, 0, 3, 6]
sorted(a,reverse=True)
ans:
[6, 3, 2, 1, 0, 0, 0]
from typing import List
def move(A:List[int]):
    j=0 # track of nonzero elements
    k=-1 # track of zeroes
    size=len(A)
    for i in range(size):
        if A[i]!=0:
            A[j]=A[i]
            j+=1
        elif A[i]==0:
            A[k]=0
            k-=1

since we have to keep the relative order.因为我们必须保持相对顺序。 when you see nonzero element, place that nonzero into the index of jth.当您看到非零元素时,将该非零元素放入 jth 的索引中。

first_nonzero=A[0]  # j=0
second_nonzero=A[1] # j=1
third_nonzero=A[2]  # j=2

With k we keep track of 0 elements.使用 k 我们跟踪 0 个元素。 In python A[-1] refers to the last element of the array.在 python 中 A[-1] 指的是数组的最后一个元素。

first_zero=A[-1]  # k=-1
second_zero=A[-2] # k=-2
third_zero= A[-3] # k=-3
a = [4,6,0,6,0,7,0]
a = filter (lambda x : x!= 0, a) + [0]*a.count(0)
[4, 6, 6, 7, 0, 0, 0]

You can try my solution if you like如果您愿意,可以尝试我的解决方案

class Solution:
def moveZeroes(self, nums: List[int]) -> None:
    
    for num in nums:
        if num == 0:
            nums.remove(num)
            nums.append(num)

I have tried this code in leetcode & my submission got accepted using above code.我已经在 leetcode 中尝试过这段代码,我的提交使用上面的代码被接受了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM