【Luogu】P1923 Find the k-th smallest number (divide and conquer + quick sort)

Title description

Enter n (n <5000000 and n is an odd number) numbers ai (0 <ai <1 0 9) n (n<5000000 and n is an odd number) numbers a_i(0<a_(i)<10^9)n(n<. 5 0 0 0 0 0 0 , and n is an odd number ) a number of words ai(0<ai<109 ), output thekk ofthese numbersThe number of k is small. The smallest number is0 00 small.
Please try not to use nth_element to write this question, because the focus of this question is to practice the divide and conquer algorithm.

Sample input and output

Input
5 1
4 3 2 1 5

Output
2

Topic link: P1923 Find the kth smallest number

Ideas:

  • You can sort the array directly and output the kth.
  • Divide and conquer: use the idea of ​​quick sorting, choose the first number (or the last number) as the benchmark temp, put the number less than or equal to the benchmark on the left, and the number greater than the benchmark on the right, then the benchmark number is The position is the same as its position in the sorted array. The above operation is called a division, and each division will return a benchmark number. If the position of the reference number after division is k, it means that the current reference number is the k-th number, and it is output directly. If the position of the current reference number is greater than k, it means that the k-th largest number is in the right interval of the reference number and only needs to be divided again in the right interval. Otherwise, in the left interval, just divide and search in the left interval.

Divide and conquer code:

//AC代码:
#include<iostream>
#include<cstdio>
    using namespace std;
    const int N=5e6+100;
    int a[N];
    //做一次划分,归位基准数
    int p(int num[],int l,int r){
    
    
    int temp=num[l];
    while(l<r){
    
    
    while(l<r&&num[r]>temp) r--;
    num[l]=num[r];
    while(l<r&&num[l]<=temp) l++;
    num[r]=num[l];
    }
    num[l]=temp;
    return l;
    }
    //分治查找第k小的数
    int quicksort(int num[],int l,int r,int k){
    
    
    int x=p(num,l,r);
    if(x==k) return num[k];
    return x>k ? quicksort(num,l,x-1,k) :  quicksort(num,x+1,r,k);
    }
    int main(){
    
    
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    printf("%d\n",quicksort(a,0,n-1,k));
    return 0;
    }

Use nth_element:

  • Seeing this function for the first time, it seems to be useful, get familiar with it:

Header file <algorithm>
void nth_element (RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last);
void nth_element (first, nth, last);
Function: return the nth number in the interval [first, last).

//AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
    using namespace std;
    const int N=5e6+100;
    int a[N];
    int main(){
    
    
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    nth_element(a,a+k,a+n);   
    printf("%d\n",a[k]);
    return 0;
    }
  • It can be seen that nth_element(a,a+k,a+n) returns the element at the original "address a+k" in the array, "a+0" is the 0th smallest.

Guess you like

Origin blog.csdn.net/IAMLSL/article/details/115251462