zoukankan      html  css  js  c++  java
  • 第k小数3

    给定两个升序的整型数组A和B。将A和B中的元素两辆相加可以得到数组C,现在给你数组A和B,求由数组A和B两辆相加得到的数组C中,第k小的数字时多少。

    采用二分的方法

    显然答案在【a[1] + b[1],a[n] + b[m]】的区间,即下界为a[1] + b[1], 上界为a[n] + b[m],反复枚举上下界的中间值mid与k比较以缩小范围即可找到答案。

    假设a[] = 【1,2, 3, 4, 5】,b[] = 【6,7,8,9,10】,mid = a[1] + b[1] = 7, max = a[5] + b[5] = 15, mid = (min + max) / 2 = 11。

    从a[1]到a[m],一次逆序与b数组的元素相加,若某一轮中a[i] 加到b[j]时两数和不大于k,则该轮中比k值小的元素的个数为j。

    下一轮a[i + 1]与b数组逆序相加时,直接从b[j]开始加即可,因为很显然的,a[i + 1] > a[i]。

    累加所有比k值小的元素个数即为mid在两数组中的排序数。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long LL;
     7 LL A[100000], B[100000];
     8 
     9 int compare(const void *p, const void *q)//函数指针
    10 /*在这句话里 p,q肯定是一个指针变量
    11 (int *)p是表示把p强制转换成一个int型的指针。
    12 如果以前p是char型,编译器会认为p指向的那一个字节的内存单元是p里面的东西
    13 把a转换成int型,编译器会认为a指向的连续四个字节里的东西都是p里面的。
    14 *(int *)p就是取p指向的内容的意思,跟*p的那个*作用一样*/
    15 {
    16     return *(LL *)p - *(LL *)q;
    17 }
    18 
    19 LL cal(LL A[], LL m, LL B[], LL n, LL mid)//计算mid值在两数组中的排序数
    20 {
    21     LL i, j;
    22     LL cnt = 0;
    23     j = n - 1;
    24     for(i = 0; i < m; ++i)
    25     {
    26         while(j >= 0 && A[i] + B[j] > mid)//定位B数组中相加比mid小的位置
    27             --j;                            //累计
    28         cnt += (j + 1);
    29     }
    30     return cnt;
    31 }
    32 LL findKth(LL A[], LL m, LL B[], LL n, LL k)
    33 {
    34     LL min = A[0] + B[0];
    35     LL max = A[m - 1] + B[n - 1];
    36     LL mid;
    37     LL ans;
    38 
    39     while(min <= max)
    40     {
    41         mid = ((max - min) >> 1) + min;
    42         if(k <= cal(A, m, B, n, mid))
    43             max = mid - 1;
    44         else
    45             min = mid + 1;
    46     }
    47 }
    48 
    49 int main()
    50 {
    51     LL m, n, k, i;
    52     while(scanf("%lld%lld%lld", &m, &n, &k) != EOF)
    53     {
    54         for(i = 0; i < m; ++i)
    55             cin >> A[i];
    56         for(i = 0; i < n; ++i)
    57             cin >> B[i];
    58         qsort(A, m, sizeof(LL), compare);
    59         qsort(B, n, sizeof(LL), compare);
    60         cout << findKth(A, m, B, n, k);
    61     }
    62     return 0;
    63 }

    将cal函数也采用二分查找的方式计算小于等于k的数字个数

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 long long a[109999];
     8 long long b[109999];
     9 long long n, m;
    10 
    11 
    12 long long cmp(long long a, long long b)
    13 {
    14     return a < b;
    15 }
    16 
    17 long long cal(long long v)
    18 {
    19     long long ll, rr, mid, i, add = 0;
    20     long long min, max;
    21     for(i = 1; i <= n; i++)
    22     {
    23         min = a[i] + b[1];
    24         max = a[i] + b[m];
    25         if(v < min)
    26             break;
    27         if(v >= max)
    28         {
    29             add += m;
    30             continue;
    31         }
    32         ll = 1;
    33         rr = m;
    34         while(ll <= rr)
    35         {
    36             mid = (ll + rr) / 2;
    37             if(v < (a[i] + b[mid]))
    38                 rr = mid - 1;
    39             else
    40                 ll = mid + 1;
    41         }
    42         if(v != (a[i] + b[ll]))
    43             ll--;
    44         add += ll;
    45     }
    46     return mid;
    47 }
    48 
    49 long long find(long long ll, long long rr, long long k)
    50 {
    51     long long mid, i;
    52     while(ll <= rr)
    53     {
    54         mid = (ll + rr) / 2;
    55         if(k < cal(mid))
    56             rr = mid - 1;
    57         else
    58             ll = mid + 1;
    59     }
    60     return ll;
    61 }
    62 
    63 int main()
    64 {
    65     long long k, ll, rr;
    66     while(scanf("%ld%ld%ld", &n, &m, &k) != EOF)
    67     {
    68         long long i;
    69         for(i = 1; i <= n; i++)
    70             cin >> a[i];
    71         for(i = 1; i <= m; i++)
    72             cin >> b[i];
    73         sort(&a[1], &a[n + 1], cmp);
    74         sort(&b[1], &b[1 + m], cmp);
    75 
    76         ll = a[1] + b[1];
    77         rr = a[n] + b[m];
    78 
    79         cout << find(ll, rr, k) << endl;
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    笔试题 9.11
    shell脚本编程
    android源码中用到的设计模式
    struts2.0的工作流程
    无奈的信息产业部备案网站流程
    VS2005调试时弹出“无法附加。绑定句柄无效”对话框
    彻底删除项目的VSS源代码管理信息
    软件版本详细介绍
    导入SourceSafe过程中项目结构无法修改问题的解决方案
    建立良好的客户关系=节约项目成本
  • 原文地址:https://www.cnblogs.com/CZT-TS/p/8447760.html
Copyright © 2011-2022 走看看