• 牛客网剑指offer第29题——最小的k个数


    题目:

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

    分析:

    思路一:我们可以利用STL库的sort函数,先将数组排序(时间复杂度O(nlogn),再选前K个数。

    代码如下:

     vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
            vector<int>res;
            if(k == 0 || input.size() == 0 || k > input.size())
                return res;
            sort(input.begin(),input.end());
            for(int i =0;i < k;i++)
                res.push_back(input[i]);
            return res;

    代码很简单,而又朴实无华。

    但是很明显有些浪费,因为我们并不关心其余N-K个元素的顺序,上述做法反而做了多余的工作。

    那么更好的思路是:采用快速排序的思想:找前K个值。

    毫无疑问的是,快速排序的思想是很朴素的:让正确的元素出现在正确的位置:什么意思?就是:如果一个数;它前面的所有元素都小于它(我们并不关心它前面的元素是否拍好序),其后面额元素都大于它,那么这个数就处在正确的位置;举例:3 1 2 4 7 9 6,对于数字4,它前面的元素都小于它,它后面的元素都大于它,因此4出于正确的位置(正确的位置的含义是:即使这个数组完全排好序,这个数的位置索引仍然是不变的)。那么上述问题就变成了:我们让一组数据的前K个数,使得他们都处在一个正确的位置。

     1  vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
     2         vector<int>res;
     3         if(k == 0 || input.size() == 0 || k > input.size())
     4             return res;
     5         int start =0;
     6         int end = input.size()-1;
     7         int bounder = partition(input,start,end);
     8         while(bounder != k-1)
     9         {
    10             if(bounder  < k-1)
    11                 start = bounder+1;
    12            else
    13                 end = bounder-1;
    14             bounder = partition(input,start,end);
    15         }
    16         for(int i =0;i < k;i++)
    17             res.push_back(input[i]);
    18         return res;
    19     }
    20        int partition(vector<int>& input, int l,int r)
    21         {
    22             int tmp = input[l];
    23             while(l < r)
    24             {
    25                 while( l < r && input[r] > tmp) r--;
    26                 swap(input[l],input[r]);
    27                 while(l < r && input[l] <= tmp) l++;
    28                 swap(input[l],input[r]);
    29             }
    30             input[l] = tmp;
    31             return l;
    32         }

    解释代码:

    第20——32行的代码:称之为partition,其作用是:对于一个随机的数组vector,我们处理其最左端的数据。也就是input[0],最终使得input[0]处在一个正确的位置(也就是让其前面的数比它小,后面的数比它大),并返回这个位置。

    我们来解读一下:这个位置bounder表达的含义:这个位置前的数都比这个位置的数小,后面的数都比它大;换句话说:前面的bounder-1个是就是这个数组前bounder-1个最小的数!!!

    现在主程序也就是第2行到第18行的代码,如果bounder大于k了,说明bounder前面的数多于k个,很明显我们要缩小partition的范围;而bounder小于k,说明bounder前面的数还不够k个,我们需要进一步搜索。总而言之,我们需要使得找到的bounder正好使得bouder 前面的数和bounder处的数。一共有k个。

  • 相关阅读:
    easyui combobox 的取值问题
    关于Java中集合的讲解~
    面试中经常会被问到的70个问题
    80端口被NT kernel & System 占用pid 4
    java中try{}catch{}和finally{}的执行顺序问题
    Java中基本数据类型的存储方式和相关内存的处理方式(java程序员必读经典)
    String,StringBuffer和StringBuilder三者的讲解
    String是基本的数据类型吗?
    jdk中那些常见的类不能被继承的
    关于java中getClass()和getSuperClass()的讲解
  • 原文地址:https://www.cnblogs.com/shaonianpi/p/12692174.html
Copyright © 2020-2023  润新知