剑指offer--面试题30:最小的K个数



题目描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
python实现:
# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution2(self, tinput, k):
        # write code here
        # 法1:直接排序,选取前k个最小的,最快时间复杂度O(nlogn)
        # 法2:利用大顶堆,时间复杂度O(n),空间复杂度O(k),
        # 方法:比堆顶小,则入堆,挤掉堆顶,最后剩下的就是最小的k个数
        n = len(tinput)
        if n == 0 or k > n or k <= 0:
            return []
        if n == k:
            return sorted(tinput)
        
        import heapq # 注意:默认是小顶堆,但我们要实现大顶堆,所以入堆时数值可以取反
        heap = []
        heapq.heapify(heap) # 将列表“堆化”
        for num in tinput:
            if len(heap)<k:
                heapq.heappush(heap, -num)
            else: # ==
                if num < -heap[0]: # 比堆顶小
                    heapq.heappop(heap) # 删除堆顶
                    heapq.heappush(heap, -num)
        return sorted([-x for x in heap]) # sorted 返回 list
    
    
    
    # 法2:基于快排:当一次partition后返回轴枢的idx,如果idx>k,则直接看到idx后面的数,因为他们肯定
    # 不是最小的k个数;如果idx==k-1,则刚好找到
    # 如果idx<k,则砍掉idx前的数,并令k=k-idx
    def GetLeastNumbers_Solution(self, tinput, k):
        n = len(tinput)
        if n == 0 or k > n or k <= 0:
            return []
        if n == k:
            return sorted(tinput)

        low, high = 0, n-1
        idx = self.partition(tinput, low, high)
        while idx != k-1:
            if idx > k-1:
                high = idx-1
            else:
                low = idx+1
                # k = k-(idx+1)
            idx = self.partition(tinput, low, high)
        # 此时idx==k-1 
        return sorted(tinput[:k])

    def partition(self, nums, low, high):
        pivot = nums[low]
        while low<high:
            while low<high and nums[high]>=pivot:
                high -= 1
            nums[low] = nums[high]
            # low += 1
            while low<high and nums[low]<=pivot:
                low += 1
            nums[high] = nums[low]
            high -= 1
        nums[low] = pivot
        return low
c++实现:
class Solution {
public:
    //法1:堆
    vector<int> GetLeastNumbers_Solution1(vector<int> input, int k) {
        priority_queue<int> hq;//默认是大顶堆(优先队列)
        vector<int> result;
        if(input.empty() || k>input.size() || k<=0)
            return result;
        if(k==input.size()){
            sort(input.begin(), input.end());
            return input;
        }
          
        for(auto num : input){
            if(hq.size()<k){
                hq.push(num);
            }else{
                hq.push(num);
                hq.pop();
            }
        }
          
        //for(auto num:hq)
        //    result.push_back(num);
        while(!hq.empty()){
            int top = hq.top();
            hq.pop();
            result.push_back(top);
        }
        sort(result.begin(), result.end());
        return result;
              
    }
      
      
      
    //法2:基于快排
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        //vector<int> result;
        if(input.empty() || k>input.size() || k<=0)
            return {};
        if(k==input.size()){
            sort(input.begin(), input.end());
            return input;
        }
          
        int low=0, high=input.size()-1;
        int idx = partition(input, low, high);
        while(idx!=k-1){
            if(idx>k-1){
                high = idx-1;
                idx = partition(input, low, high);
            }else{
                low = idx+1;
                idx = partition(input, low, high);
            }
        }
          
        //for(int i=0; i<k; i++)
        //    result.push_back(input[i]);
        vector<int> result(input.begin(), input.begin()+k);
        //sort(result.begin(), result.end());
        return result;
    }
      
    int partition(vector<int> &numbers, int low, int high){
        int pivot = numbers[low];
        while(low<high){
            while(low<high && numbers[high]>=pivot){
                high--;
            }
            numbers[low] = numbers[high];
            //numbers[low++] = numbers[high];
            while(low<high && numbers[low]<=pivot){
                low++;
            }
            numbers[high] = numbers[low];
            //numbers[high--] = numbers[low];
        }
        numbers[low] = pivot;
        return low;
            
    }
};

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值