【剑指Offer】(数组)最小的K个数(Partition分割)

该博客探讨了一道编程题目,目标是给定一个整数数组,找出其中最小的K个数。博主提供了问题描述和解决方案,旨在帮助读者理解如何高效地解决此类问题。

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

题目链接https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&tqId=11182&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述

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

解决方法
class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> res;
        if (k<=0 || input.size()<k) return res;
        //方法1:排序后查找,时间O(nlogn)
        /*sort(input.begin(),input.end());
        for (int i=0;i<k;i++)
            res.push_back(input[i]);
        return res;*/
        //方法2:利用分割策略,以第k个元素为基准,左边的数字都比他小,右边的都比他大,时间O(n)
        int start=0,end=input.size()-1;
        int index=Partition(input,start,end);
        while(index!=k-1){
            if(index>k-1) end=index-1;
            else start=index+1;
            index=Partition(input,start,end);
        }
        for (int i=0;i<k;i++)
            res.push_back(input[i]);
        return res;

    }
    int Partition(vector<int> &data,int left,int right){
        int pi=data[left];
        while(left<right){
            while(left<right && data[right]>pi) right--;
            data[left]=data[right];
            while(left<right && data[left]<=pi) left++;
            data[right]=data[left];
        }
        data[left]=pi;
        return left;
    }
};
要在一个整数数组中找到第k小的元素,你可以使用一种叫做“快速选择”(QuickSelect)的算法,它是快速排序算法的一个变种,用于查找中位数或指定位置的元素。这种方法的时间复杂度通常是O(n),在最坏情况下是O(n^2)但这种情况非常罕见。 以下是一个简单的快速选择算法的伪代码实现: ```c // 快速选择函数 int quickSelect(int arr[], int left, int right, int k) { if (left == right) // 如果只有一个元素,直接返回 return arr[left]; // 基准值的选择,这里通常随机选取 int pivotIndex = partition(arr, left, right); // 如果基准值的位置就是我们要找的k,直接返回 if (pivotIndex == k - 1) return arr[pivotIndex]; else if (pivotIndex < k - 1) // 第k个元素在基准值右边,递归右半部分 return quickSelect(arr, pivotIndex + 1, right, k); else // 第k个元素在基准值左边,递归左半部分 return quickSelect(arr, left, pivotIndex - 1, k); } // 分区函数,返回基准值的新位置 int partition(int arr[], int left, int right) { int pivot = arr[right]; // 常用最后一个元素作为基准值 int i = left - 1; for (int j = left; j < right; j++) { if (arr[j] <= pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[right]); // 将基准值放到正确的位置 return i + 1; } ``` 使用这个函数,你可以像下面这样调用它来找出第k小的元素: ```c int main() { int arr[] = {5, 8, 2, 6, 9, 1}; // 示例数组 int n = sizeof(arr) / sizeof(arr[0]); int k = 3; // 指定查找第3小的元素 int result = quickSelect(arr, 0, n - 1, k - 1); // 注意k-1是因为数组索引从0开始 printf("The %dth smallest number in the array is %d\n", k, result); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值