2

什么是对列表进行排序的最有效方法,[0,0,1,0,1,1,0]其元素仅为0& 1,而不使用任何内置sort()sorted()count()函数。O(n) 或小于

4

10 回答 10

11
>>> lst = [0,0,1,0,1,1,0]
>>> l, s = len(lst), sum(lst)
>>> result = [0] * (l - s) + [1] * s
>>> result
[0, 0, 0, 0, 1, 1, 1]
于 2012-06-24T07:21:47.800 回答
4

可以使用许多不同的通用排序算法。但是,在这种情况下,最重要的考虑是所有要排序的元素都属于集合 (0,1)。

正如其他贡献者所回答的那样,有一个简单的实现。

def radix_sort(a):
    slist = [[],[]]
    for elem in a:
        slist[elem].append(elem)
    return slist[0] + slist[1]

print radix_sort([0,0,1,0,1,1,0])

必须注意,这是基数排序的一种特殊实现。如果要排序的列表的元素属于定义的有限集合,这可以很容易地扩展。

def radix_sort(a, elems):
    slist = {}
    for elem in elems:
        slist[elem] = []
    for elem in a:
        slist[elem].append(elem)
    nslist = []
    for elem in elems:
        nslist += slist[elem]
    return nslist

print radix_sort([2,0,0,1,3,0,1,1,0],[0,1,2,3])

没有sort()sorted()count()功能。在)

于 2012-06-24T07:36:47.973 回答
2

这个是O(n)(你不能少):

old = [0,0,1,0,1,1,0]
zeroes = old.count(0) #you gotta count them somehow!
new = [0]*zeroes + [1]*(len(old) - zeroes)

由于没有 Python 循环,这可能是您在纯 Python 中获得的更快...

于 2012-06-24T07:21:56.660 回答
1

def sort_arr_with_zero_one():

  main_list = [0,0,1,0,1,1,0]
  zero_list = []
  one_list = []
  for i in main_list:
    if i:
        one_list.append(i)
    else:
        zero_list.append(i)

  return zero_list + one_list
于 2012-06-24T07:26:50.210 回答
0

您只有两个值,因此您提前知道输出的精确结构:它将分为两个不同长度的区域。

于 2012-06-24T07:16:47.520 回答
0

我会试试这个:

b = [0,0,1,0,1,1,0]

def odd_sort(a):
  zeroes = a.count(0)

  return [0 for i in xrange(zeroes)] + [1 for i in xrange(len(a) - zeroes)]
于 2012-06-24T07:22:21.300 回答
0

您可以使用两个指针遍历列表,一个从开始(i)开始,一个从结束(j)开始,并逐一比较值并在必要时交换它们:

def sort_binary_values(l):
    i, j = 0, len(l)-1
    while i < j:
        # skip 0 values from the begin
        while i < j and l[i] == 0:
            i = i+1
        if i >= j: break
        # skip 1 values from the end
        while i < j and l[j] == 1:
            j = j-1
        if i >= j: break
        # since all in sequence values have been skipped and i and j did not reach each other
        # we encountered a pair that is out of order and needs to be swapped
        l[i], l[j] = l[j], l[i]
        j = j-1
        i = i+1
    return l
于 2012-06-24T07:25:17.473 回答
0

我喜欢 JBernado 的答案,但会抛出另一个可怕的选项(尽管我没有对其进行任何分析 - 它不是特别可扩展,因为它依赖于字典哈希的顺序,但适用于 0 和 1):

from itertools import chain, repeat
from collections import Counter

list(chain.from_iterable(map(repeat, *zip(*Counter(bits).items()))))

或者 - 稍微不那么复杂......

from itertools import repeat, chain, islice, ifilter
from operator import not_

list(islice(chain(ifilter(not_, bits), repeat(1)), len(bits)))

这应该使一切都保持在 C 级别 - 所以它应该是相当优化的。

于 2012-06-24T10:26:14.410 回答
0

您只需要知道原始序列有多长以及其中有多少。

old = [0,0,1,0,1,1,0]
ones = sum(1 for b in old if b)
new = [0]*(len(old)-ones) + [1]*ones
于 2012-06-24T10:33:57.347 回答
0

这是 O(n) 时间和 O(2) 空间的 Python 解决方案。

绝对不需要创建新列表和最佳时间表现

def sort01(arr):
  i = 0
  j = len(arr)-1
  while i < j:
    while arr[i] == 0:
      i += 1
    while arr[j] == 1:
      j -= 1
    if i<j:
      arr[i] = 0
      arr[j] = 1
  return arr
于 2021-05-19T10:43:45.317 回答