[C++日常小题] 寻找第k大数字(numberk)
Description
经过长时间的筹备工作,在Jourk,Ronny,Plipala,阿长,阿沈等人的努力下,DM实验室建立起自己的系列网站,其中包括三个大板块:DMOJ首页、DMOJ论坛、DMOJ博客。
作为一个大型的网站,数据的加工处理需要用到很多算法系统模块,通过这些模块对系统主数据库进行修改。因此,在构建DMOJ系列网站的过程中,编写了一个庞大的数据统计系统,其中包括一个寻找第k大数字的模块,对于一个数据库来说,这样一个模块的重要性不容置疑。但是,由于在修改网站的过程中,这个模块被不慎删掉了,DMOJ找到了聪明的你,希望你能帮DMOJ重写这个模块。
对于输入数据,你将按数据要求找出n个数字中的第k大数字。
关于第k大数字的解释:对于一个数字序列,计算该数字序列第k大数字,一种可行但效率不高的方法是,首先剔除数字序列中重复的数字,然后通过某种排序算法,获得剔除重复数字后的数字序列从大到小排序的数字序列,然后取从大到小排序的数字序列的第k位的数字。从另一个角度,题目中的第k大数字即是不计入数字序列中数字重复出现的部分,对于数字重复出现的情况,应该认为该数字只出现一次。
现在请聪明的你尝试设计一种可行且效率更高的方法来解决这个问题。
Input
输入数据一共有三行。
第一行有一个正整数n(n<=10000000),表示一共给出多少个数字。
第二行有一个正整数k(k<=10000000),表示要求你找出第k大数字。
第三行有n个整数,给出n个数字。对于每个整数i,均满足-10000000<=i<=10000000。
Output
输出文件共一行,包含一个整数,表示n个数字中第k大数字是多少。
Sample Input
3
2
2006 2007 2008
Sample Output
2007
解题思路
一道经典的找第 k 大数字,但是这里题目要求的是 对于数字重复出现的情况,应该认为该数字只出现一次 ,即先要保证存储的数字是唯一的,我用STL里的 bitset
来保证数字的唯一性。
开一个大小为 20000001 的 bitset
,0 ~ 10000000 位表示数字 -10000000 ~ 0; 10000001 ~ 20000000 位表示数字 1 ~ 10000000。每输入一个数字,用该数字加一个偏移量 10000000 的值,再用 bitset::test
来检测是否存在,存在则什么都不做,不存在就存到数组 nums
中,用 size
来记录存储数字的数量。
剩下的就是找第 k 大数的问题。
主要函数为 int findk(int left, int right, int pos)
。
与快排不同的是快排是对划分出的两组都进行递归处理,而这道题只用对其中一组递归处理就可以了,每次递归都只对其中一组处理,可以很快的找到解。
我写的代码是按从大到小划分数组,每次划分好后,有三种情况:
注: 下面代码中主元的下标为 j,为第 j - left + 1 个元素
- 若主元位置正好是第 k 个元素,则返回该值;
- 若主元位置小于第 k 个元素,则在右边一组找第 k - (j - left + 1) 大数字;
- 若主元位置大于第 k 个元素,则在左边一组找第 k 大数字;
Code
#include <bits/stdc++.h>
using namespace std;int n, k, size = 0;
vector<int> nums(10000001);
bitset<20000001> exist(0);int findk(int left, int right, int pos);
void exchange(int posA, int posB);int main() {int tmp, bitpos;scanf("%d%d", &n, &k);for (int i = 0; i < n; ++i) {scanf("%d", &tmp);bitpos = tmp + 10000000;if (!exist.test(bitpos)) {exist.set(bitpos);nums[size++] = tmp;}}printf("%d\n", findk(0, size - 1, k));return 0;
}void exchange(int posA, int posB) {int tmp = nums[posA];nums[posA] = nums[posB];nums[posB] = tmp;
}int findk(int left, int right, int pos) {int main = nums[left];int i = left + 1, j = right;while (i <= j) {while (nums[i] > main) i++;while (nums[j] < main) j--;if (i < j) exchange(i, j);}exchange(left, j);int length = j - left + 1;if (length == pos) return nums[j];else if (length > pos) return findk(left, j - 1, pos);else return findk(j + 1, right, pos - length);
}
这么写代码的话,OJ 返回的 Run Time 为 2.62sec。
有大神只用了 0.82sec,只能膜了。
以上所有,如有错误,麻烦指出,我会及时更改的。
[C++日常小题] 寻找第k大数字(numberk)相关推荐
- 网易2016 实习研发工程师 [编程题]寻找第K大 and leetcode 215. Kth Largest Element in an Array...
传送门 有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数. 给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在. 测试样例: [1,3,5, ...
- 网易2016实习研发工程师编程题——寻找第K大
1.题目 有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数. 给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在. 测试样例: [1,3,5 ...
- 牛客 寻找第k大数字
题目描述 有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数. 给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在. 示例1 输入 [1,3, ...
- 牛客题霸 [寻找第K大] C++题解/答案
牛客题霸 [寻找第K大] C++题解/答案 题目描述 有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数. 给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的 ...
- 面试官:海量无序数据,寻找第 K 大的数,越快越好
最近在参加阿里云举办的<第三届数据库大赛创新上云性能挑战赛--高性能分析型查询引擎赛道>,传送门: https://tianchi.aliyun.com/competition/entra ...
- 海量无序数据寻找第 K 大的数
前言 最近在参加阿里云举办的<第三届数据库大赛创新上云性能挑战赛--高性能分析型查询引擎赛道>,传送门:https://tianchi.aliyun.com/competition/ent ...
- java中二叉树中第k大的数,寻找第k大的数
目录: 1.引子 2.排序解决法 3.类快排解法 4.最小堆解法 1.引子 日常编码中,常见遇到这样的问题,"寻找最大的数",此问题非常容易,可暴力直接遍历找出,也可使用分冶策略找 ...
- 【算法】寻找第k大的数
目录: 1.引子 2.排序解决法 3.类快排解法 4.最小堆解法 1.引子 日常编码中,常见遇到这样的问题,"寻找最大的数",此问题非常容易,可暴力直接遍历找出,也可使用分冶策略找 ...
- 寻找第K大元素的八大算法、源码及拓展
寻找第K大元素的八大算法.源码及拓展 http://www.cnblogs.com/bethunebtj/p/4861378.html 一.问题描述 所谓"第(前)k大数问题"指的 ...
最新文章
- php 替换回车tab,PHP替换回车换行符的三种方法
- iOS无法引入头文件
- Linux下oracle数据库spfile参数配置文件丢失问题解决,“ORA-32001: write to SPFILE requested but no SPFILE is in use“问题处理
- 微信营销这么做,你就成功了 转载
- Java 抽象类、接口
- Python中的openpyxl如何对excel修改文件
- 【STL学习】自己动手C++编程实现hash table(散列表)
- access用扫描枪输入_判断是否扫码枪输入的通用函数源码
- Android FAE工程师要求,使用AndroidStudio进行系统应用开发
- 深入浅出之正则表达式(一)(转)
- 基于深度学习的视觉目标跟踪方法介绍
- 流畅的Python笔记
- NOIP2017提高组广东省成绩
- 微信公众号 JS接口安全域名 配置
- (4.6.14)android 插桩基本概念plugging or Swap
- 电脑突然上不了网,而且ping网关可以通
- wsdl和soap协议详细解析
- matlab kmo检验,RPCL(Rival Penalized Competitive Learning)在matlab下的实现
- c语言输入f1到f11,我来告诉你:电脑键盘的F1至F12正确用处
- Vs2019创建新项目时,没有任何模板,导致无法创建新项目
热门文章
- tryhackme圣诞挑战2021-Advent of Cyber 3-day2-越权漏洞,修改cookie
- 【mask2former】环境配置+cityscapes全景分割
- 中国人要在太空安家!今天先把大厅送了上去
- 基础连接已经关闭: 接收时发生意外错误
- 华夫饼为什么不松软_只需半个小时,教你轻松制作松软“华夫饼”,健康美味无添加...
- 2021.12.9号学习dockerfile内容
- HTTP报500错误的原因
- 【ZLR-T81 200A漏电继电器】
- 一种高效快速的高密度椒盐噪声消除算法(吕宗伟等)
- Leetcode刷题 Day4~Day5