链接:https://www.nowcoder.com/questionTerminal/a6a656249f404eb498d16b2f8eaa2c60
来源:牛客网
设有n个正整数,将他们连接成一排,组成一个最大的多位整数。
如:n=3时,3个整数13,312,343,连成的最大整数为34331213。
如:n=4时,4个整数7,13,4,246连接成的最大整数为7424613。
输入描述:
有多组测试样例,每组测试样例包含两行,第一行为一个整数N(N<=100),第二行包含N个数(每个数不超过1000,空格分开)。
输出描述:
每组数据输出一个表示最大的整数。
示例1
输入
2
12 123
4
7 13 4 246
输出
12312
7424613
时间复杂度O(n的平方)的方法
import sys
import time
def cmp(l1,l2):
#print("l1 is",l1)
#print("l2 is",l2)
s1=str(l1)+str(l2)
s2=str(l2)+str(l1)
#print("s1 is",s1,"s2 is",s2)
for i in range(0,len(s1)):
#print("s1[",i,"] is",s1[i])
if int(s1[i])>int(s2[i]):
#print("first False")
return False
if int(s1[i])<int(s2[i]):
#print("secod True")
return True
return False
#starttime = time.time()
n = int(sys.stdin.readline().strip())
l = list(map(int, sys.stdin.readline().strip().split()))
for i in range(0,n):
for j in range(i+1,n):
#print("current i is", i, "cur j is", j, "cur l is", l)
if cmp(l[i],l[j]):
l[i],l[j]=l[j],l[i]
strsl=list(map(str,l))
res=''.join(strsl)
print(res)
#endtime = time.time()
#print(endtime-starttime)
这个方法在牛客网上也能通过,但是在vm的笔试中就只有36%,因为超时。
我分析这个算法类似冒泡排序的思想,时间复杂度是O(n的平方)
对第二组实例的运行时间为14.653626680374146
我在想如何改进,查到https://blog.csdn.net/kobe2016/article/details/79144534
这篇博客里说 python自带的sorted()算法,最坏的时间复杂度是O(nlogn)
所以改用python自带的sort算法试一下
而且python3自带的sort函数不接受直接使用cmp了,要自定义比较规则,而且比较函数还不接受两个参数,如果想接受两个参数,必须调用from functools
import cmp_to_key
import sys
from functools import cmp_to_key
#import time
def mycmp(a, b):
ab = int(a+b)
ba = int(b+a)
return 1 if ab > ba else -1
#starttime = time.time()
num = int(sys.stdin.readline().strip())
l= sys.stdin.readline().strip().split()
ls=sorted(l,key=cmp_to_key(mycmp),reverse=True)
print (''.join(ls))
按理说因为调用的是python自带的sorted()所以时间复杂度应该变低呀,变成O(nlogn)呀,为什么反而增加成了26.910626649856567秒呢?可能是因为把重新申请了存储ls那么大空间消耗时间?看到一个解释:
https://stackoverflow.com/questions/11547588/why-is-pythons-sorted-slower-than-copy-then-sort
l.sort和sorted(l)的代码是一样的,时间差别在于sorted copy的时候是用的泛型代码,可以对任何可迭代的对象copy副本用于排序,当然我们也可以假设原来的类型就是list。
list.sort can work with a known size, and swap elements within that size, sorted() has to work with unknown sizes and generic iterables, and thus may have to allocate memory as it builds (possibly forcing a memcpy if not contig.), but this should be minimal as you’ve stated. Copying a list is fairly simple as that’s just a simple malloc/memcpy op (and creation of a new PyObject*) –
但是
from functools import cmp_to_key
import time
def mycmp(a, b):
ab = int(a+b)
ba = int(b+a)
return 1 if ab > ba else -1
starttime = time.time()
num = int(sys.stdin.readline().strip())
l= sys.stdin.readline().strip().split()
l.sort(key=cmp_to_key(mycmp),reverse=True)
print (''.join(l))
endtime = time.time()
print(endtime-starttime)
用l.sort()原址排序这种方法确实快了很多啊,
对测试样例2的用时是3.3400912284851074
总结:
算法精髓:
1.代码的核心首先是定义一个ab和ba的比较
刚开始还考虑最高位相比,然后依次相比,写法比ab 和ba这种比较要麻烦
2.冒泡排序的O(n2)超时,考虑使用python自带的sorted()函数将时间复杂度降低至O(nlogn)
3.速度从快到慢,list.sort()>sorted(list)>冒泡排序