题目:
输入整数数组 arr
,找出其中最小的 k
个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例:
输入:arr = [3,2,1], k = 2 输出:[1,2] 或者 [2,1]
输入:arr = [0,1,2,1], k = 1 输出:[0]
解题思路:
解法一:(排序法)时间复杂度O(nlogn)
直接将整个列表排序。最后输出前k个数。
arr.sort()
return arr[:k]
解法二:(大顶堆)
1,特殊情况k=0时直接输出空列表
2,k>0时,先添加k个元素进列表hp(加入的元素放相反数,因为次数要区分的是最大值,而堆默认的是将最小值放在堆顶);然后对将列表hp进行最大顶堆排序(也就是将最大值放在堆顶),然后遍历k+1至len(arr)元素,如果当前元素arr[i]的相反数比堆顶元素大,就将堆顶元素删除,并将当前元素arr[i]的相反数放进堆(排序时已使用heapq堆库,已将列表转化为堆,具有大顶堆的特点,后面使用堆库,都会自动保持大顶堆特点)。最后返回hp列表的相反数即可。
if k==0:
return []
else:
hp=[]
hp=[-i for i in (arr[:k])] #此时hp仅仅是列表
heapq.heapify(hp) #使用堆库,变成了堆
for i in arr[k:]:
if -hp[0]>i:
heapq.heappop(hp) #删除堆顶那个最大元素
heapq.heappush(hp,-i) #将当前元素添加进堆
ans=[]
for i in hp:
ans.append(-i)
return ans
知识:
1、认识堆
堆也是列表的特殊形式。使用heapq堆库,就能将普通列表转化成堆,后续只要使用堆库添加方式,就是自动选出最小值放在堆顶(堆顶是指的第一个元素)。
注意:堆是默认小顶堆,意思就是堆顶是最小值。
因为此题是要从堆中找出最大值,故取相反数存放,使用堆的小顶堆特点。
2、堆的操作
heapq.heapify(hp) #将列表hp进行最小值放堆顶操作
heapq.heappop(hp) #将堆顶元素删除
heapq.headpush(hp, -i) #将元素-i放进堆hp中,并进行最小值放堆顶操作(每放一个值进去,就会找出最小值放堆顶)
这个和列表hp.append(-i)方式有区别,列表添加元素仅仅放元素进去,但不会找出最小值放堆顶。
解法三:(快排)
具体怎么做就不深究了。
思想是:
1,先选择一个元素当哨兵,然后将整个列表依次与哨兵比较,比哨兵大就放哨兵右边,比哨兵小就放哨兵左边
2,比较一下k与哨兵的索引,如果刚好是k,输出索引0至k-1位置元素;
如果k小于哨兵索引,则将哨兵左边元素再一次选哨兵分大小,找出最小k个元素(递归)
如果k大于哨兵索引,则将哨兵右边元素再一次选哨兵分大小,找出最小的k-index(哨兵)-1个最小元素(递归)
学完递归再来实现代码。。。