目录:
一. 设计一个O(n)复杂度的算法
1、问题:计数排序
- 现在有一个列表,列表中的数范围都在0到100之间,列表长度大约为100万,设计算法在O(n)时间复杂度内将列表进行排序
2、原理
- 必须知道这些数中最大的数是多少
- 然后生成一个长度等于最大数的列表
- 循环li列表中所有的数,li中每出现一次这个数就在生成的count列表中加一
- 这样就可以在count列表中的对应位置记录出列表li中所有数出现的次数
- 然后在循环count,这个数出现几次就依次写几个到li列表中,就出现下面效果
答案:
def count_sort(li, max_num):
count = [0 for i in range(max_num + 1)]
for num in li:
count[num] += 1
i = 0
print('count',count)
for num,m in enumerate(count): #循环列表count,按顺序得到li中数出现次数
for j in range(m): #这个数出现多少次就在li中依次追加多少个
li[i] = num
i += 1
li = [3,4,5,3,2,4,5,6,7,4]
count_sort(li,10)
print(li) #[2, 3, 3, 4, 4, 4, 5, 5, 6, 7]
二. 在大量数中找到前10个最大的数
1、问题
- 现在有n个数(n>10000),设计算法,按大小顺序得到前世大的数。
- 应用场景:榜单TOP 10
2、使用插入法解决思路(时间复杂度: O(kn))
- 先取出待排序列表前11个元素,使用插入排序先有序
- 然后依次循环未排序的数,一个个的替换TOP 10列表中的第11号元素,再进行一次插入排序
- 这样仅循环了一次列表即可得到前11大的元素,最后列表切片,切出前10大元素即可
插入法解决:
# 一趟插入
def insert(li,i):
tmp = li[i] # tmp是无序区取出的一个数
j = i - 1 # li[j]是有序区最大的那个数
while j >= 0 and li[j] < tmp:
#li[j] < tmp 这个条件的大于号小于号控制是10个最大的数还是最小的数
li[j + 1] = li[j] # 将有序区最右边的数向右移一个位置
j = j - 1
li[j + 1] = tmp # 将tmp放到以前有序区最大数的位置,再依次与前一个数比较
def insert_sort(li):
for i in range(1, len(li)):
insert(li, i)
def topk(li,k):
top = li[0:k+1]
insert_sort(top) #先将列表中的11个元素用插入法排序
for i in range(k+1, len(li)): #循环后面剩下的元素
top[k] = li[i] #依次取后面未排序的数放到top列表的最后面
insert(top, k)