剑指 Offer 40. 最小的k个数

这篇博客介绍了如何使用快速排序算法找到数组中的最小k个数。博主首先提供了使用内置排序函数的简单解决方案,然后详细解释了快速排序的原理,并给出了一种优化的快速排序实现,其中基准元素在遍历过程中不移动,最后通过交换将其放置在正确位置。这种方法减少了交换次数,提高了效率。博主还分享了一种更简洁的快速排序代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源:剑指 Offer 40. 最小的k个数

问题描述:

在这里插入图片描述


解题分析:

这题没什么难度,就是把数组排序,然后取出前k个。
之所以写出来,就是因为我好像很久没写快排了

方法一:使用sort直接排序

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        sort(arr.begin(),arr.end());
        vector<int>nums;
        if(k==0)
        {
            return nums;
        }
        while(k>=1)
        {
            nums.push_back(arr[k-1]);
            k--;
        }
        return nums;
    }
};

方法二:回顾一下快排

快速排序的基本思想: 通过一趟排序将数组分割成2个部分,其中一部分要比基准数小,一部分要比基准数大,再按照这种方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,是整个数组变成有序序列。
一般取数组最左边的数做基准数。把小于基准数的移到基准数的左边,大于基准数的移到基准数的右边,相等的数不移动。

快速排序的操作:

设最左边下标为 i i i,最右边下标为 j j j. 首先从数组的右边进行查找,也就是进行 j − − j-- j操作,找到了比基准数小的,让基准数与其进行交换。然后从从左边进行查找,也就是进行 i + + i++ i++操作,找到了比基准数大的,让基准数与其进行交换。直到 i 与 j i与j ij相遇结束。
过程如图所示:
在这里插入图片描述
但是我研究了下评论,发现了一个简单的写法,就是每次交换可以不用交换基准数的位置
而是把扫描到的不合适的 i 和 j i和j ij进行交换
遍历了一遍后
把基准数和num[i]交换。
然后在左边右边进行递归.
如代码所示:

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        //快排
        quickSort(arr,0,arr.size()-1);
        
        vector<int>nums;
        if(k==0)
        {
            return nums;
        }
        while(k>=1)
        {
            nums.push_back(arr[k-1]);
            k--;
        }
        return nums;

    }
private:
    void quickSort(vector<int>& arr,int left,int right)
    {
        if(left>=right) return;
        //取最左边为基准数
        int i=left,j=right;
        while(i<j)
        {
            while(i<j && arr[j]>=arr[left]) j--; //如果右边的数字 小于基准数,就进行交换;否则,就继续往前走
            while(i<j && arr[i]<=arr[left]) i++;//如果左边的数字 大于基准数,就进行交换;否则,就继续往后走
            swap(arr[i],arr[j]);
        }
        swap(arr[i],arr[left]); //把基准数放在中间
        //划分左右区间
        quickSort(arr,left,i-1);
        quickSort(arr,i+1,right);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

寒江雪ing

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

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

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

打赏作者

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

抵扣说明:

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

余额充值