首页 > 其他分享 >P1923 【深基9.例4】求第 k 小的数

P1923 【深基9.例4】求第 k 小的数

时间:2024-02-13 22:44:49浏览次数:22  
标签:P1923 这里 int 深基 arr nth currNum 函数

1.题目

【深基9.例4】求第 k 小的数

题目描述

输入 \(n\)(\(1 \le n < 5000000\) 且 \(n\) 为奇数)个数字 \(a_i\)(\(1 \le a_i < {10}^9\)),输出这些数字的第 \(k\) 小的数。最小的数是第 \(0\) 小。

请尽量不要使用 nth_element 来写本题,因为本题的重点在于练习分治算法。

输入格式

输出格式

样例 #1

样例输入 #1

5 1
4 3 2 1 5

样例输出 #1

2

2.题解

2.1 分治算法

0.注意

这里我一直有两个测试点过不去,经过资料查阅之后得知:cin,cout的读入输出效率过慢,因为他们有着缓冲机制和一些其他安全措施,但是这里读入的数1≤n<5000000过多
这里可以选择使用scanf和printf,或者像我这里使用快读的方法
这里的inline是内联函数的意思,直接将函数复制到相应位置,而不是调用函数,通过栈保存上下文信息,对于频繁使用的函数提高了效率

1.思路

这里最终l和r的位置有两种情况:

只要注意l的位置是右区间的边界,而r的位置是左区间的边界即可。
而若是有 k >= l,说明k的值在右区间内,若是k==l不就是arr[l]呢?因为右区间内的数并不是顺序排列,无法判断是否就是第k大的数
如果 k <= r同理;
还有一种可能就是l和r位置的第二种情况,k在他们之间,这时候实际上就是找到了需要的那个数,这里可以像我这里继续递归,然后通过返回条件返回该值,也可以直接输出该值。

2.代码

#include<bits/stdc++.h>
using namespace std;
int k, ans;
//这里arr必须设置为全局变量,不然每次都作为函数输入参数,会消耗大量资源和时间爱你 
vector<int> arr;

void swap(int i, int j){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

// 这里由于cin读入过慢,而这里n( 1≤n<5000000且n为奇数),所以使用快读缩短读取时间爱
inline int read(){	//快读 
    char ch=getchar();
	int x=0,f=1;
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    } 
	while('0'<=ch&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    } return x*f;
}

void sortNum(int begin, int end){
	if(begin == end){
		ans = arr[begin];
		return;
	}
    int l = begin, r = end;
    int currNum = arr[(end - begin) / 2 + begin];
    while(l <= r){
    	//由于我取的currNum是中位数,所以l第一次最多停留在中位数,r同理 
    	//由于后面if中的交换,l指向的必是小于等于currNum的值,r指向的必是大于等于currNum的值
		//后续的几次while循环,必不可能在while循环中出现 l > r的情况,最多是 l = r; 
        while(arr[l] < currNum) l++; //l指向第一个不小于currNum的值 
        while(arr[r] > currNum) r--; //r指向第一个不大于currNum的值
        if(l <= r){
            swap(l, r);
            l++;
            r--;
        }
    }
    // 结束后l和r有两种情况:1. r+1 = l; 2. r+1 = l - 1; 
    // l指向的是右区间边界, r指向的是左区间边界 
    if(k >= l)  sortNum(l, end); // 表明在右区间 
    else if(k <= r) sortNum(begin, r); //表明在左区间 
	//除去上面两种,这里只有一种情况:r + 1 = k = l - 1; 
    else {
        sortNum(r+1 , l-1);
	}
}

int main(){
    int n;
    n = read();
    k = read();
    arr.resize(n);
    for(int i = 0; i < n; i++){
    	arr[i] = read();
    }
    sortNum(0, n - 1);
    cout << ans;
    return 0;
}

2.2 nth_element函数

思路

在强大的STL库中存在一个神奇的函数,那就是nth_element,这个函数主要用来将数组元素中第k小的整数排出来并在数组中就位,随时调用,可谓十分实用。
函数语句:nth_element(数组名,数组名+第k小元素,数组名+元素个数)

代码

#include<bits/stdc++.h>
using namespace std;
long long n,k,a[5000010];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    nth_element(a,a+k,a+n);//使第k小整数就位 
    printf("%d",a[k]);//调用第k小整数
}

标签:P1923,这里,int,深基,arr,nth,currNum,函数
From: https://www.cnblogs.com/trmbh12/p/18014894

相关文章

  • 洛谷P5725 【深基4.习8】求三角形
    洛谷P5725【深基4.习8】求三角形【深基4.习8】求三角形题目描述模仿例题,打印出不同方向的正方形,然后打印三角形矩阵。中间有个空行。输入格式输入矩阵的规模,不超过9。输出格式输出矩形和正方形样例#1样例输入#14样例输出#101020304050607080910111213141516......
  • P1271 【深基9.例1】选举学生会
    1.题目介绍【深基9.例1】选举学生会题目描述学校正在选举学生会成员,有\(n\)(\(n\le999\))名候选人,每名候选人编号分别从\(1\)到\(n\),现在收集到了\(m\)(\(m\le2000000\))张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。输入格......
  • P5711 【深基3.例3】闰年判断
    题目写在开头:本题并不容易出错,但是需要一些常识,记录的目的也只是为了代码优化原题目位于:[P5711【深基3.例3】闰年判断-洛谷|计算机科学教育新生态(luogu.com.cn)]【深基3.例3】闰年判断题目描述输入一个年份,判断这一年是否是闰年,如果是输出$1$,否则输出$0$。输入格式......
  • P2433 【深基1-2】小学数学 N 合一
    题目原题目在[P2433【深基1-2】小学数学N合一-洛谷|计算机科学教育新生态(luogu.com.cn)]【深基1-2】小学数学N合一题目描述问题1请输出IloveLuogu!问题2这里有$10$个苹果,小A拿走了$2$个,Uim拿走了$4$个,八尾勇拿走剩下的所有的苹果。我们想知道:小......
  • 【洛谷 P2249】【深基13.例1】查找(向量+二分查找+递归)
    【深基13.例1】查找题目描述输入个不超过的单调不减的(就是后面的数字不小于前面的数字)非负整数,然后进行次询问。对于每次询问,给出一个整数,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出。输入格式第一行个整数和,表示数字个数和询问次数。第二行......
  • 【洛谷 P2249】【深基13.例1】查找(向量+lower_bound)
    【深基13.例1】查找题目描述输入个不超过的单调不减的(就是后面的数字不小于前面的数字)非负整数,然后进行次询问。对于每次询问,给出一个整数,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出。输入格式第一行个整数和,表示数字个数和询问次数。第二行......
  • 洛谷题单指南-排序-P1923 【深基9.例4】求第 k 小的数
    原题链接:https://www.luogu.com.cn/problem/P1923题意解读:要最快的求第k小的数,O(n)的做法是利用快排的思想对数据进行划分第一步、取分界点x,通常设x=a[(l+r)/2]第二步、将小于x的挪到x左边,将大于x的挪到x右边第三步、比较,如果x左边的个数大于k,则继续递归处理左边,否则递......
  • P5739 【深基7.例7】计算阶乘
    1.题目介绍【深基7.例7】计算阶乘题目描述求\(n!\),也就是\(1\times2\times3\dots\timesn\)。挑战:尝试不使用循环语句(for、while)完成这个任务。输入格式第一行输入一个正整数\(n\)。输出格式输出一个正整数,表示\(n!\)。样例#1样例输入#13样例输出#16提示......
  • P5738 【深基7.例4】歌唱比赛
    1.题目介绍【深基7.例4】歌唱比赛题目描述\(n(n\le100)\)名同学参加歌唱比赛,并接受\(m(m\le20)\)名评委的评分,评分范围是\(0\)到\(10\)分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下\(m-2\)个评分的平均数。请问得分最高的同学分数是多少?......
  • P5737 【深基7.例3】闰年展示
    1.题目介绍【深基7.例3】闰年展示题目描述输入\(x,y\),输出\([x,y]\)区间中闰年个数,并在下一行输出所有闰年年份数字,使用空格隔开。输入格式输入两个正整数\(x,y\),以空格隔开。输出格式第一行输出一个正整数,表示\([x,y]\)区间中闰年个数。第二行输出若干个正整数,按照......