设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。
示例:
输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3,4]提示:
0 <= len(arr) <= 100000 0 <= k <= min(100000, len(arr))想简单点,就是排序问题,然后输出前k个元素即可。我们要掌握的是排序算法,因为快速排序是面试最常考的排序算法,也是各个算法库基本都会内置的排序方法,因此,这里给出快速排序的实现。
快速排序思想:分治。 选定一个pivot,每一轮要保证pivot左侧都更小、右侧都更大。如何做到?指针对撞 [3, 1, 6, 2, 4, 5]选3为pivot,i=0,j=5; j指针向左移动,5-4-3,j=3时arr[j]=2,这时让arr[i]=arr[j],变为:[2, 1, 6, 2, 4, 5]; i指针向右移动,0-1-2,i=2时arr[i]=6,这时让arr[j]=arr[i],变为:[2, 1, 6, 6, 4, 5]; j指针向左移动,3-2,j=2时i=j,这时让arr[i]=pivot,变为:[2, 1, 3, 6, 4, 5]; 好了,现在对3的左侧和右侧分别进行同样的处理就可以了。
现在来看该思路具体实现:
class Solution: def smallestK(self, arr: List[int], k: int) -> List[int]: self.quickSort(arr, 0, len(arr) - 1) return arr[:k] # 快速排序,分治思想 def quickSort(self, arr, left, right): if left < right: pivotIndex = self.partition(arr, left, right) self.quickSort(arr, left, pivotIndex - 1) self.quickSort(arr, pivotIndex + 1, right) # 每次调用partition()的结果就是pivot前面的元素都比pivot小、后面的元素都比pivot大 def partition(self, arr, i, j): pivot = arr[i] while i < j: # j指针从右到左,直到找到小于pivot的元素,交换 while i < j and arr[j] >= pivot: j -= 1 arr[i] = arr[j] # i指针从左到右,直到找到大于pivot的元素,交换 while i < j and arr[i] <= pivot: i += 1 arr[j] = arr[i] # 最后i==j,这个位置是pivot,左侧都比pivot小、右侧都比pivot大 arr[i] = pivot return i为了便于记忆,记住几个关键点,面试时回忆基本会想起来。 快速排序:pivot,分治(递归),指针对撞,交换。
当然可以直接这样:
arr.sort() return arr[0:k]或这样:
# heapq为最小堆 return heapq.nsmallest(k, arr) # 当然,更好的方法是heapq始终维持k个元素然后全输出