简体   繁体   中英

Sort a list efficiently which contains only 0 and 1 without using any builtin python sort function?

What is the most efficient way to sort a list, [0,0,1,0,1,1,0] whose elements are only 0 & 1 , without using any builtin sort() or sorted() or count() function. O(n) or less than that

>>> 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]

There are many different general sorting algorithms that can be used. However, in this case, the most important consideration is that all the elements to sort belong to the set (0,1).

As other contributors answered there is a trivial implementation.

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])

It must be noted that this is a particular implementation of the Radix sort . And this can be extended easily if the elements of the list to be sorted belong to a defined limited set.

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])

No sort() or sorted() or count() function. O(n)

This one is O(n) (you can't get less):

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

As there are no Python loops, this may be the faster you can get in pure Python...

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

You have only two values, so you know in advance the precise structure of the output: it will be divided into two regions of varying lengths.

I'd try this:

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)]

You could walk the list with two pointers, one from the start ( i ) and from the end ( j ), and compare the values one by one and swap them if necessary:

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

I like the answer by JBernado, but will throw in another monstrous option (although I've not done any profiling on it - it's not particulary extensible as it relies on the order of a dictionary hash, but works for 0 and 1):

from itertools import chain, repeat
from collections import Counter

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

Or - slightly less convoluted...

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

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

This should keep everything at the C level - so it should be fairly optimal.

All you need to know is how long the original sequence is and how many ones are in it.

old = [0,0,1,0,1,1,0]
ones = sum(1 for b in old if b)
new = [0]*(len(old)-ones) + [1]*ones

Here is a Python solution in O(n) time and O(2) space.

Absolutely no need to create new lists and best time performance

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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