排序-029-最小的K个数(堆排序)(快速排序)

题目描述

输入n个整数,找出其中最小的K个数。例如输入 4,5,1,6,2,7,3,8 这8个数字,则最小的4个数字是 1,2,3,4

分析

解题思路一:排序思想

  • 思路: 按照升序排序,然后取前K个数,就是我们最终想要的到的结果,现在较好一点的排序方法时间复杂度是NlogN,我们还有更快的实现方法吗?

解题思路二:快排思想

  • 思路:根据一次快排(Partition)的想法,可知一次随机快速排序可以确定一个有序的位置,这个位置的左边都小于这个数,右边都大于这个数,我们如果能找到随机快速排序确定的位置等于k-1的那个位置,那么0~k-1个数就是我们要找的数。怎么能找到那个位置:
    - 如果Partition确定的位置小于K-1,说明k-1这个位置在它的右边,我们继续在右边进行查找。
    - 如果Partition确定的位置大于K-1,说明k-1这个位置在它的左边,我们继续在左边进行查找。

  • 缺点: 时间复杂度虽然是O(n),但是找出来的最小的K个数却不是排序过的。而且这种方法有个限制,就是必须修改给的数组

解题思路三:堆排思想

  • 适用: 处理海量数据在线数据。

  • 思路:是建一个K个数的大顶堆,每次拿一个数和堆顶元素比较,如果这个数比堆顶元素,则必然不是最小的K个数,如果这个数比堆顶元素,则与堆顶元素交换,然后在向下调整一次建成新的大堆,然后遍历所有的数,直到最小的K个数都进堆里。

    • 最大的K个数---- 建小顶堆
    • 最小的K个数----建大顶堆
  • 优点:海量数据不占内存实时判别新产生的数据;时间复杂度O(nlogn)

代码

解题思路一:排序思想

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        if tinput==None or tinput==[] or k<0 or k>len(tinput):
            return []
         
        tinput.sort()
        return tinput[:k]

解题思路二:快排思想

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        n = len(tinput)
        if k <= 0 or k > n:
            return list()
        start = 0
        end = n - 1
        mid = self.partition(tinput, start, end)
        while k - 1 != mid:
            if k - 1 > mid:
                start = mid + 1
                mid = self.partition(tinput, start, end)
            elif k - 1 < mid:
                end = mid - 1
                mid = self.partition(tinput, start, end)
        res = tinput[:mid+1]
        # res.sort()
        return res
        
    def partition(self, numbers, low, high):
        key = numbers[low]
        while low < high:
            while low < high and numbers[high] >= key:
                high -= 1
            numbers[low] = numbers[high]
            while low < high and numbers[low] <= key:
                low += 1
            numbers[high] = numbers[low]
        numbers[low] = key
        return low

解题思路三:堆排思想

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        if k > len(tinput) or k == 0:
            return []
        self.arr = [0]
        for one in tinput:
            self.arr.append(one)
        self.heap_sort(self.arr, k)
        return [_ for _ in reversed(self.arr[-k:])]
    
    def sift(self, begin, n):
        i = begin
        j = 2*i
        tmp = self.arr[i]
        while j <= n:
            if j < n and self.arr[j] > self.arr[j+1]:
                j += 1  # 右孩子小
            if tmp > self.arr[j]:
                self.arr[i] = self.arr[j]
                i = j
                j = 2*i
            else:
                break
        self.arr[i] = tmp
        pass
 
    def heap_sort(self, data, k):
        n = len(data) - 1
        for i in range(int(n/2), 0, -1):  # 初始化构建小顶堆 -- 得到的结果是从小到大
            self.sift(i, n)
 
        # 最小3个数
        for i in range(n, n-k, -1):
            self.arr[1], self.arr[i] = self.arr[i], self.arr[1]
            self.sift(1, i-1)
        pass
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TransientYear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值