题目
输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8 这8个数字,则最小的4个数字是1、2、3、4。
方法一:(最简单的思路)整体排序后取前k个数
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
return sorted(arr)[:k]
复杂度:O(nlogn)
方法二:k轮冒泡排序
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
if k <= 0 or k > len(arr):
return []
for i in range(k):
for j in range(i+1, len(arr)):
if arr[i] > arr[j]:
arr[i], arr[j] = arr[j], arr[i]
return arr[:k]
复杂度:O(kn)
如果k很大,超出时间限制,
快排中的Partition思想
①随机选一数为key,在partition函数中完成一轮比较的结果是,比key大的数都在其右边,比key小的数放在其左边。返回 key的index。
②判断index与k的大小:
如果 index > k,说明前k小的数在key左边,故需把寻找范围缩小,在key左侧找。
如果 index < k,说明上轮partition之后,前index个数找的太少了,我们需要再往数组的后面找。
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
if k <= 0 or k > len(arr):
return []
start = 0
end = len(arr) - 1
mid = self.partion(arr, start, end)
while k - 1 != mid:
if k - 1 < mid:
end = mid - 1
mid = self.partion(arr, start, end)
elif k - 1 > mid:
start = mid + 1
mid = self.partion(arr, start, end)
return arr[:k]
def partion(self, nums, low, high):
key = nums[low]
while low < high:
while low < high and nums[high] >= key:
high -= 1
nums[low] = nums[high]
while low < high and nums[low] <= key:
low += 1
nums[high] = nums[low]
nums[low] = key
return low
# 注意partion中判断大小一定要有等号,否则会陷入死循环
# 注意判断k的极值
时间复杂度: 因为我们是要找下标为k的元素,第一次切分的时候需要遍历整个数组 (0 ~ n) 找到了下标是 j 的元素,假如 k 比 j 小的话,那么我们下次切分只要遍历数组 (0~k-1)的元素就行啦,反之如果 k 比 j 大的话,那下次切分只要遍历数组 (k+1~n) 的元素就行啦,总之可以看作每次调用 partition 遍历的元素数目都是上一次遍历的 1/2,因此时间复杂度是 N + N/2 + N/4 + … + N/N = 2N, 因此时间复杂度是 O(N)
堆排序
heap:寻找找到一堆数中的最大值或者最小值的数据结构
一个很常见的例子,假设我们要选5个最矮的同学参加比赛,候选人选好之后又跑来一个新同学参加评选。这个时候新同学只需要PK候选人中最高的,如果他比最高的还高,就被淘汰,如果比最高的矮,他就可以替代这个最高的。按照这个思想,无论再来多少新同学都可以很快速的选择。
以这个思想为基础,为了最快的找到候选人中最高的,以身高为基准建立大顶堆,每次新人与堆顶PK,PK结束之后维护候选人重新为大顶堆。
这种思想将时间复杂度降到以k为基数,每次调整堆的时间复杂度都是,那么整体时间复杂度为。
现成
# -*- coding:utf-8 -*-
import heapq
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
if len(tinput) < k:
return []
return heapq.nsmallest(k, tinput)
手写堆
https://blog.csdn.net/qq_20141867/article/details/81152894
这篇博客探讨了在给定整数数组中找出最小k个数的几种方法,包括整体排序、k轮冒泡排序、基于快速排序的Partition思想和堆排序。通过详细解释每种方法的实现原理和时间复杂度,展示了如何在不同情况下优化查找效率。

504

被折叠的 条评论
为什么被折叠?



