题目描述:

给定两个整型数组A和B。我们将A和B中的元素两两相加可以得到数组C。
譬如A为[1,2],B为[3,4].那么由A和B中的元素两两相加得到的数组C为[4,5,5,6]。
现在给你数组A和B,求由A和B两两相加得到的数组C中,第K小的数字。

输入:

输入可能包含多个测试案例。
对于每个测试案例,输入的第一行为三个整数m,n, k(1<=m,n<=100000, 1<= k <= n *m):n,m代表将要输入数组A和B的长度。
紧接着两行, 分别有m和n个数, 代表数组A和B中的元素。数组元素范围为[0,1e9]。

输出:

对应每个测试案例,
输出由A和B中元素两两相加得到的数组c中第K小的数字。

样例输入:
  1. 2 2 3
  2. 1 2
  3. 3 4
  4. 3 3 4
  5. 1 2 7
  6. 3 4 5
样例输出:
  1. 5
  2. 6
  3.  
  4. 此题真的很难。这个题的难度在于数组的长度非常长长长长长长长长长长长长长长长长长长长长,我开始的代码是这样的:
  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <string>
  5. #include <algorithm>
  6. #define MAX 100009
  7.  
  8. long long A[MAX];
  9. long long B[MAX];
  10. long long C[MAX];
  11.  
  12. int cmp(const void *a, const void *b) {
  13. long long at = *(long long *)a;
  14. long long bt = *(long long *)b;
  15. return (int)(at - bt);
  16. }
  17.  
  18. int main(int argc, char const *argv[])
  19. {
  20. int m, n, k;
  21. while(scanf("%d %d %d",&m, &n, &k) != EOF) {
  22. for(int i = ; i < m; i++) {
  23. scanf("%lld",&A[i]);
  24. }
  25. for(int i = ; i < n; i++) {
  26. scanf("%lld",&B[i]);
  27. }
  28. int t = ;
  29. for(int i = ; i < m; i++) {
  30. for(int j = ; j < n; j++) {
  31. C[t] = A[i] + B[j];
  32. t++;
  33. }
  34. }
  35.  
  36. qsort(C, t, sizeof(long long), cmp);
  37. printf("%lld\n", C[k-]);
  38. }
  39. return ;
  40. }

结果就run time error了

之后才明白此题需要用二分搜索,现对A,B两个数组排序,可知道他们的最大值,最小值。那么所要求的第几小的数字必然在这两个值之间,我们此时采用二分搜索的办法去找到这个值。具体的做法是先求出中间值mid,在求出中间值mid在序列中是第几小的数字,从而改变max值和min值,再不断的求下去。但一开始还是超时了,

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <string>
  5. #include <algorithm>
  6. #define MAX 100009
  7.  
  8. long long A[MAX];
  9. long long B[MAX];
  10.  
  11. int cmp(const void *a, const void *b) {
  12. long long at = *(long long *)a;
  13. long long bt = *(long long *)b;
  14. return (int)(at - bt);
  15. }
  16.  
  17. long long findbit(long long mid, long long n, long long m) {
  18. int ans = n*m;
  19. for(long long int i = ; i < n; i++) {
  20. for(long long int j = m -; j >= ; j--) {
  21. if(A[i] + B[j] > mid) {
  22. ans--;
  23. }
  24. else {
  25. break;
  26. }
  27. }
  28. }
  29. return ans;
  30. }
  31.  
  32. int main(int argc, char const *argv[])
  33. {
  34. long long int m, n, k;
  35. //freopen("input.txt","r",stdin);
  36. while(scanf("%lld %lld %lld",&m, &n, &k) != EOF) {
  37. for(int i = ; i < m; i++) {
  38. scanf("%lld",&A[i]);
  39. }
  40. for(int i = ; i < n; i++) {
  41. scanf("%lld",&B[i]);
  42. }
  43.  
  44. qsort(A, n, sizeof(long long),cmp);
  45. qsort(B, m, sizeof(long long),cmp);
  46.  
  47. long long max = A[n - ] + B[m - ];
  48. long long min = A[] + B[];
  49. long long mid;
  50.  
  51. while(min <= max) {
  52. mid = (max + min)/;
  53. long long midBit = findbit(mid, n, m);
  54. if(k <= midBit) {
  55. max = mid - ;
  56. }
  57. else {
  58. min = mid + ;
  59. }
  60. }
  61.  
  62. printf("%lld\n",min);
  63. }
  64. return ;
  65. }

超时的原因在于findBit内的二层循环。我们如果将第一个数组从小到大遍历,而将第二个数组从大到小遍历,比如下面

6 9 11

8 11 13

如果a[0] + b[1] > 15, (6 +11 > 15),那么a[1] + b[1] 必然也大于15,因为a[1] > a[0], a[1] + b[2]也必然大于15,因为b[2] > b[1]

所以需要遍历每一个a,而对于b只需要进行局部的遍历。

也就是说,对于a[0]生成的序列,mid是第mid0 = j+1小的数字,那么对于a[1], j只需要从上一个j开始算起,因为前面的肯定比mid要大。

代码如下

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <string>
  5. #include <algorithm>
  6. #define MAX 100009
  7.  
  8. long long A[MAX];
  9. long long B[MAX];
  10.  
  11. int cmp(const void *a, const void *b) {
  12. long long at = *(long long *)a;
  13. long long bt = *(long long *)b;
  14. return (int)(at - bt);
  15. }
  16.  
  17. long long findbit(long long mid, long long n, long long m) {
  18. long long int ans = ;
  19.  
  20. long long int j = m - ;
  21. for(long long int i = ; i < n; i++) {
  22. while(j >= && A[i] + B[j] > mid) {
  23. j--;
  24. }
  25. ans = ans + j + ;
  26. }
  27. return ans;
  28. }
  29.  
  30. int main(int argc, char const *argv[])
  31. {
  32. long long int m, n, k;
  33. //freopen("input.txt","r",stdin);
  34. while(scanf("%lld %lld %lld",&m, &n, &k) != EOF) {
  35. for(int i = ; i < m; i++) {
  36. scanf("%lld",&A[i]);
  37. }
  38. for(int i = ; i < n; i++) {
  39. scanf("%lld",&B[i]);
  40. }
  41.  
  42. qsort(A, n, sizeof(long long),cmp);
  43. qsort(B, m, sizeof(long long),cmp);
  44.  
  45. long long max = A[n - ] + B[m - ];
  46. long long min = A[] + B[];
  47. long long mid;
  48.  
  49. while(min <= max) {
  50. mid = (max + min)/;
  51. long long midBit = findbit(mid, n, m);
  52. if(k <= midBit) {
  53. max = mid - ;
  54. }
  55. else {
  56. min = mid + ;
  57. }
  58. }
  59.  
  60. printf("%lld\n",min);
  61. }
  62. return ;
  63. }

九度oj 题目1534:数组中第K小的数字的更多相关文章

  1. 九度OJ 1534 数组中第K小的数字 -- 二分查找

    题目地址:http://ac.jobdu.com/problem.php?pid=1534 题目描述: 给定两个整型数组A和B.我们将A和B中的元素两两相加可以得到数组C. 譬如A为[1,2],B为[ ...

  2. 数组中第K小的数字(Google面试题)

    http://ac.jobdu.com/problem.php?pid=1534 题目1534:数组中第K小的数字 时间限制:2 秒 内存限制:128 兆 特殊判题:否 提交:1120 解决:208 ...

  3. 九度OJ 题目1534:数组中第K小的数字(二分解)

    题目链接:点击打开链接 题目描述: 给定两个整型数组A和B.我们将A和B中的元素两两相加可以得到数组C. 譬如A为[1,2],B为[3,4].那么由A和B中的元素两两相加得到的数组C为[4,5,5,6 ...

  4. 九度 1534:数组中第K小的数字(二分法变形)

    题目描述: 给定两个整型数组A和B.我们将A和B中的元素两两相加可以得到数组C.譬如A为[1,2],B为[3,4].那么由A和B中的元素两两相加得到的数组C为[4,5,5,6].现在给你数组A和B,求 ...

  5. 题目1534:数组中第K小的数字 ——二分

    http://ac.jobdu.com/problem.php?pid=1534 给定两个整型数组A和B.我们将A和B中的元素两两相加可以得到数组C.譬如A为[1,2],B为[3,4].那么由A和B中 ...

  6. 九度OJ 1351:数组中只出现一次的数字 (位运算)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3098 解决:906 题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 输入: 每个 ...

  7. 九度OJ 1348:数组中的逆序对 (排序、归并排序)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2777 解决:656 题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组 ...

  8. 九度OJ 题目1371:最小的K个数

    题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 输入: 每个测试案例包括2行: 第一行为2个整数n,k(1< ...

  9. 九度OJ 题目1384:二维数组中的查找

    /********************************* * 日期:2013-10-11 * 作者:SJF0115 * 题号: 九度OJ 题目1384:二维数组中的查找 * 来源:http ...

随机推荐

  1. JavaScript数据格式验证探讨

    1.需求 修改某个文本框数据,要求对修改后的格式做验证(必须是数字). 注:实际需求比上述复杂,为了说明问题,这里特意简化了需求(如:对修改后数据依赖条件的判断,数据入库等). 2.关于NaN的探讨( ...

  2. 洛谷 P2126 Mzc家中的男家丁

    题目背景 mzc与djn的…还没有众人皆知,所以我们要来宣传一下. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁,现在mzc要将她们全都聚集起来(干什么就不知道了).现在知道mzc与男家丁们互 ...

  3. bunzip2命令

    bunzip2——解压缩.bz2格式文件 命令所在路径:/usr/bin/bunzip2 示例1: # bunzip2 yum.log.bz2 解压当前目录下的yum.log.bz2为yum.log, ...

  4. 在Mac里给Terminal终端自定义颜色

    Mac里终端显示默认是一种颜色,太单调了. 然而我们可以自定义这些颜色显示.进入-目录,编辑文件.bash_profile, 输入如下内容: 第三行那些fxfxax看起来是不是像天书?实际上是有规律的 ...

  5. Python 学习日志9月20日

    9月20日 周三 多大年龄了,还活得像个小孩.——急什么,人生又不长. 你习惯了思考宇宙星辰,一百年真的不长,一生也就不那么长,许多人的价值观念你也就无法理解.同样,许多人也无法理解你的价值观念,感兴 ...

  6. Python 类变量,成员变量,静态变量,局部变量

    局部 class TestClass(object): val1 = 100 def __init__(self): self.val2 = 200 def fcn(self,val = 400): ...

  7. javaEE(11)_事务处理

    一.事务的概念 •事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功. •例如:A——B转帐,对应于如下两条sql语句 update from account set mon ...

  8. 【JavaScript】两种常见JS面向对象写法

    基于构造函数 function Circle(r) { this.r = r; } Circle.PI = 3.14159; Circle.prototype.area = function() { ...

  9. vs code背景图片的设置

    使用vs code编辑器的时候,每次看到黑色的背景,会感觉到很大的视觉疲劳,今天来换换背景来看下效果 你需要安装的插件是background 然后在文件 => 首选项 => 设置搜索bac ...

  10. DP入门练习

    T1 题目:codevs4815江哥的dp题a codevs4815 一个简单的DP,注意开long long(不然会全WA),以及初始条件(这题有负数,所以要把f设成极小值.还要保证转移正确). # ...