《剑指offer》python实现系列,全目录
题目描述:
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
第一想法:
sort,
1
2
3
4
5
6class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
if not tinput or len(tinput)
return []
tinput.sort()
return tinput[:k]
剑指offer方法一:
由于不要求最小的k个数按序输出,参考快排中partition函数思想:
因为快排每次都能得到基于分界点的数组,分界点左边的元素一定小于分界点上的元素。如果此分界点正好是k,则得到了最小的k个数,而不必整体排序。
最坏情况是,一直没有得到这个点,得到了一个部分排序的数组。但时间复杂度仍小于快排O(nlogn)
通过调整midValueIndex的位置,让它=K
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
if not tinput or len(tinput)
return []
low, high = 0, len(tinput)-1
midValueIndex = self.partition(tinput,low,high)
targetIndex = k-1
while targetIndex != midValueIndex:
if midValueIndex > targetIndex:
high = midValueIndex-1
midValueIndex = self.partition(tinput,low,high)
elif midValueIndex < targetIndex:
low = midValueIndex+1
midValueIndex = self.partition(tinput,low,high)
return sorted(tinput[:k])#判题程序需要sort
def partition(self,mylist,low,high):
#选择mylist[low]元素作为分界点,low和high是mylist的下标
#此函数将比分界点小的放左边,比分界点大的放右边,
#返回分界点的位置索引low
midValue = mylist[low]
while low
while low= midValue:
#mylist[high]>midvalue,high就一直左移
high -= 1
mylist[low] = mylist[high]
#high处元素小于midValue,赋给low所在位置,赋值后high处的元素就没意义了,虚位以待
while low
low += 1
mylist[high] = mylist[low] # 赋给high所在位置,
mylist[low] = midValue
return low #返回分界点索引
剑指offer方法二:适合海量数据此操作
建立一个k维容器,存储k个最小值。
如果容器中已有的数字少于k个,则直接把这次读入的整数放入容器之中;
如果容器中已有k个数字了,也就是容器已满,此时我们不能只能替换已有的数字。找出这已有的k个数中的最大值,然后拿这次待插入的整数和最大值进行比较。若比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还要大,就抛弃这个整数。
可以基于堆或者红黑树实现这个k维容器,奈何还未学到,先跳过这里