在不使用任何内置python排序函数的情况下,对仅包含0和1的列表进行有效排序?
排序列表的最有效方法是什么,在不使用任何内置python排序函数的情况下,对仅包含0和1的列表进行有效排序?,python,Python,排序列表的最有效方法是什么,[0,0,1,0,1,1,0]其元素仅为0&1,而不使用任何内置的sort()或sorted()或count()函数。O(n)或小于该值,您只有两个值,因此您可以提前知道输出的精确结构:它将被划分为两个不同长度的区域。这一个是O(n)(您不能得到更少): >>> lst = [0,0,1,0,1,1,0] >>> l, s = len(lst), sum(lst) >>> result = [0] * (l - s
[0,0,1,0,1,1,0]
其元素仅为0
&1
,而不使用任何内置的sort()
或sorted()
或count()
函数。O(n)或小于该值,您只有两个值,因此您可以提前知道输出的精确结构:它将被划分为两个不同长度的区域。这一个是O(n)
(您不能得到更少):
>>> 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]
由于没有Python循环,在纯Python中,这可能会更快…我会尝试以下方法:
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)]
您可以使用两个指针遍历列表,一个从开始(
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
def排序二进制值(l):
i、 j=0,len(l)-1
而i=j:break
#从末尾跳过1个值
当i=j:break
#因为序列中的所有值都被跳过,并且i和j没有相互到达
#我们遇到一对出现故障,需要更换
l[i],l[j]=l[j],l[i]
j=j-1
i=i+1
返回l
def sort\u arr\u with\u zero\u one():
可以使用许多不同的通用排序算法。然而,在这种情况下,最重要的考虑是所有要排序的元素都属于集合(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()
函数。O(n)我喜欢JBernado的答案,但会加入另一个可怕的选项(尽管我没有对其进行任何分析-它不是特别可扩展的,因为它依赖于字典哈希的顺序,但适用于0和1):
或-稍微不太复杂…
from itertools import repeat, chain, islice, ifilter
from operator import not_
list(islice(chain(ifilter(not_, bits), repeat(1)), len(bits)))
这将使所有内容都保持在C级别,因此它应该是相当优化的。您需要知道的是原始序列的长度以及其中有多少个序列
old = [0,0,1,0,1,1,0]
ones = sum(1 for b in old if b)
new = [0]*(len(old)-ones) + [1]*ones
这里是一个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
def sort01(arr):
i=0
j=透镜(arr)-1
而i 如果我count\u of_one=sum(old)
:)。count()对我来说快15%。使用timeit
模块,自己看看。@Blender这就是我要说的:)测试了这个解决方案以及所有其他解决方案。它是目前最快的。@Blender,[0,1]*10000=[0,1,0,1,0,1….]
。如果列表仅包含不可变对象(如1
和0
),则此语法安全:)是否确实要生成列表以获取其长度。它最好写为sum(旧版if i为1)
@Jon Clements:是的,那更好。答案更新——谢谢。请不要隐藏内置函数或数据类型(id
和set
在您的情况下),值得注意的是,第一个代码块将与任何int一起工作(至少在CPython中,其中hash(int)==int),但第二个代码块纯粹是0/1I,我选择astynax的答案作为一个,因为它有更多的投票权。但我比其他人更容易理解你的话。即使你没有使用排序,排序或计数。我想也是o(n)。谢谢你的回答
from itertools import repeat, chain, islice, ifilter
from operator import not_
list(islice(chain(ifilter(not_, bits), repeat(1)), len(bits)))
old = [0,0,1,0,1,1,0]
ones = sum(1 for b in old if b)
new = [0]*(len(old)-ones) + [1]*ones
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