剑指offer系列28之最小的k个数

34 篇文章 0 订阅
15 篇文章 0 订阅

要求

  • 时间限制:1秒
  • 空间限制:32768K
  • 热度指数:357881
  • 本题知识点: 数组

题目描述

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

思路

几种排序算法被写在了一起。

思路一:快排

如果不要求前k个数是有序的也可以用快排来完成,但是这个题目要求了前k个数有序。

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        if k <= 0 or k > len(tinput):
            return []
        self.quickSort(tinput, 0, len(tinput)-1, k)
        return tinput[:k]
    
    def quickSort(self, tinput, left, right, k):
        if left >= right:
            return 
        
        index = self.partition(tinput, left, right)
        len_left = index - left + 1
        # 说明左边已经有多于k个最小数了
        if len_left >= k:
            self.quickSort(tinput, left, index-1, k)
        else:
            self.quickSort(tinput, index+1, right, k-len_left)
        
    def partition(self, tinput, left, right):
        mid = (right - left) // 2 + left
        tinput[left], tinput[mid] = tinput[mid], tinput[left]
        tmp = tinput[left]
        while left < right:
            while left < right and tinput[right] > tmp:
                right -= 1
            tinput[left] = tinput[right]
            while left < right and tinput[left] < tmp:
                left += 1
            tinput[right] = tinput[left]
        tinput[left] = tmp
        return left
C++实现
  • 运行时间:3ms
  • 占用内存:504k
思路二:堆排序
# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        if k <= 0 or k > len(tinput):
            return []
        self.res = []
        self.heap_sort(tinput, k)
        return self.res
    
    def minHeapify(self, tinput, i, heap_size):
        left = 2 * i + 1
        right = 2 * i + 2
        min_index = i
        if left < heap_size and tinput[left] < tinput[min_index]:
            min_index = left
        if right < heap_size and tinput[right] < tinput[min_index]:
            min_index = right
        if min_index != i:
            tinput[i], tinput[min_index] = tinput[min_index], tinput[i]
            self.minHeapify(tinput, min_index, heap_size)
            
    def build_min_heap(self, tinput):
        start_idx = (len(tinput)-1) // 2
        for i in range(start_idx, -1, -1):
            self.minHeapify(tinput, i, len(tinput))
    
    def heap_sort(self, tinput, k):
        self.build_min_heap(tinput)
        for i in range(k):
            self.res.append(tinput[0])
            tinput[0], tinput[-(i+1)] = tinput[-(i+1)], tinput[0]
            self.minHeapify(tinput, 0, len(tinput)-i-1)
C++实现
  • 运行时间:4ms
  • 占用内存:468k
class Solution {
public:
    // 快排
    void quickSort(vector<int> &input, int left, int right) {
        if (left >= right)
            return;
        int i = left, j = right, tmp = input[left];
        while (i < j) {
            while (i<j && input[j]>=tmp) j--;
            if (i < j) input[i] = input[j];
            while (i<j && input[i]<=tmp) i++;
            if (i < j) input[j] = input[i];
        }
        input[i] = tmp;
        quickSort(input, left, i-1);
        quickSort(input, i+1, right);
    }
    // 堆排序
    void heapSort(vector<int> &input){
        int length = input.size();
        if (length <= 1) return;
        // 构建初始堆:从右向左,从下到上
        for (int i=length/2-1; i>=0; i--)
            adjustHeap(input, i, length);
        // 开始排序:从左到右,从上到下
        for (int j=length-1; j>=0; j--){
            swap(input[0], input[j]);
            adjustHeap(input, 0, j);
        }
    }
    void adjustHeap(vector<int> &input, int i, int length){
        int tmp = input[i]; // tmp保存的值为需要调整的节点的值,i为需要调整的节点
        // k为需要调整的节点i的左孩子;如果不需要调整,则直接退出循环
        // 如果需要调整,则下次循环需要调整的节点i变成k,即和它交换的那个孩子,k变成当前k的左孩子
        for (int k=2*i+1; k<length; k=2*k+1){
            // 让k指向比较大的那个孩子节点
            if (input[k+1]>input[k])
                k = k + 1;
            // 判断是否需要调整
            if (input[k]>tmp){
                swap(input[k], input[i]);
                i = k; // 需要交换的节点变成了i的较大的子节点,该子节点的值也变成tmp
            }
            else
                break;
        }
        
    }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int length = input.size();
        vector<int> cut_vector;
        if (length < k)
            return cut_vector;
        // 快排
        // quickSort(input, 0, length-1);
        // 堆排序
        heapSort(input);
        // vector<int>::iterator iter1 = input.begin();
        // vector<int>::iterator iter2 = input.begin() + k;
        // vector<int> cut_vector(iter1, iter2);
        for (int i=0; i<k; i++)
            cut_vector.push_back(input[i]);
        return cut_vector;
    }
};

归并排序

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        if k <= 0 or k > len(tinput):
            return []
        res = self.mergeSort(tinput, 0, len(tinput)-1)
        return res[:k]
    
    def mergeSort(self, tinput, left, right):
        if right == left:
            return tinput[left: left+1]
        
        mid = (right - left) // 2 + left
        left_part = self.mergeSort(tinput, left, mid)
        right_part = self.mergeSort(tinput, mid+1, right)
        
        return self.merge(left_part, right_part)
    
    def merge(self, left_part, right_part):
        i, j = 0, 0
        res = []
        while i < len(left_part) and j < len(right_part):
            if left_part[i] < right_part[j]:
                res.append(left_part[i])
                i += 1
            else:
                res.append(right_part[j])
                j += 1
        if i < len(left_part):
            return res + left_part[i:]
        elif j < len(right_part):
            return res + right_part[j:]
        else:
            return res
            
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值