zoukankan      html  css  js  c++  java
  • 剑指Offer

    剑指Offer - 九度1349 - 数字在排序数组中出现的次数
    2013-11-23 00:47
    题目描述:
    统计一个数字在排序数组中出现的次数。
    输入:

    每个测试案例包括两行:

    第一行有1个整数n,表示数组的大小。1<=n <= 10^6。

    第二行有n个整数,表示数组元素,每个元素均为int。

    第三行有1个整数m,表示接下来有m次查询。1<=m<=10^3。

    下面有m行,每行有一个整数k,表示要查询的数。 

    输出:
    对应每个测试案例,有m行输出,每行1整数,表示数组中该数字出现的次数。
    样例输入:
    8
    1 2 3 3 3 3 4 5
    1
    3
    
    样例输出:
    4
    题意分析:
      题目要求在一个数组中找出一个数出现的次数,
        第一种想法,当然是一次性全部数一遍,用map之类的结构保存统计结果,之后每次就可以log n复杂度查询了。时间复杂度为O(n) + m * O(log k),k是数组中不同元素的个数,空间复杂度O(k)。问题是——数组已经排序,这个特性没用到。
        第二种想法,因为数组有序,所以每次都用二分查找找出一个数的左界和右界,然后right - left + 1即为结果。对于不存在的元素,二分当然返回-1之类的NOT_FOUND值,统计结果则为0。时间复杂度为m * O(log n),空间复杂度O(1)。
      观察题目数据范围,数组长度n最大可以到10^6,查询次数m最大才10^3,如果采取上面方法一,O(n)则占了大头,不划算。所以选方法二。
      其中bsearch_left求出target在数组a[]中的左下标,bsearch_right为右下标。这俩函数写法要小心,检查好数组指针,数据范围,左右端后才能开始二分查找。
      查找到左右下标后,rr - ll + 1即为结果;查不到左右下标的话,结果为0。
      1 // 652724    zhuli19901106    1349    Accepted    点击此处查看所有case的执行结果    4932KB    1913B    720MS
      2 // 201311171831
      3 #include <cstdio>
      4 using namespace std;
      5 
      6 int bsearch_left(const int a[], int n, int target)
      7 {
      8     int ll, rr, mm;
      9     
     10     if(a == NULL || n <= 0){
     11         return -1;
     12     }
     13     
     14     if(target < a[0] || target > a[n - 1]){
     15         return -1;
     16     }
     17     
     18     // guarantee that a[left] < target && a[right] >= target
     19     if(target == a[0]){
     20         return 0;
     21     }
     22     
     23     ll = 0;
     24     rr = n - 1;
     25     while(rr - ll > 1){
     26         mm = (ll + rr) / 2;
     27         if(target > a[mm]){
     28             ll = mm;
     29         }else{
     30             rr = mm;
     31         }
     32     }
     33     
     34     if(a[rr] == target){
     35         return rr;
     36     }else{
     37         return -1;
     38     }
     39 }
     40 
     41 int bsearch_right(const int a[], int n, int target)
     42 {
     43     int ll, rr, mm;
     44     
     45     if(a == NULL || n <= 0){
     46         return -1;
     47     }
     48     
     49     if(target < a[0] || target > a[n - 1]){
     50         return -1;
     51     }
     52     
     53     // guarantee that a[left] <= target && a[right] > target
     54     if(target == a[n - 1]){
     55         return n - 1;
     56     }
     57     
     58     ll = 0;
     59     rr = n - 1;
     60     while(rr - ll > 1){
     61         mm = (ll + rr) / 2;
     62         if(target >= a[mm]){
     63             ll = mm;
     64         }else{
     65             rr = mm;
     66         }
     67     }
     68     
     69     if(a[ll] == target){
     70         return ll;
     71     }else{
     72         return -1;
     73     }
     74 }
     75 
     76 int main()
     77 {
     78     int *a = NULL;
     79     int i, n, m;
     80     int target;
     81     int ll, rr;
     82     
     83     while(scanf("%d", &n) == 1){
     84         if(n <= 0){
     85             continue;
     86         }
     87         a = new int[n];
     88         for(i = 0; i < n; ++i){
     89             scanf("%d", &a[i]);
     90         }
     91         scanf("%d", &m);
     92         for(i = 0; i < m; ++i){
     93             scanf("%d", &target);
     94             ll = bsearch_left(a, n, target);
     95             if(ll < 0){
     96                 printf("0
    ");
     97                 continue;
     98             }
     99             rr = bsearch_right(a, n, target);
    100             if(rr < 0){
    101                 printf("0
    ");
    102                 continue;
    103             }
    104             if(rr >= ll){
    105                 printf("%d
    ", rr - ll + 1);
    106             }else{
    107                 printf("0
    ");
    108             }
    109         }
    110         delete[] a;
    111         a = NULL;
    112     }
    113     
    114     return 0;
    115 }
  • 相关阅读:
    D365: 笔记(VS无法打开表浏览器)
    D365: 笔记(跟踪调试批处理代码)
    D365: 笔记(非批处理执行class中弹出交互式窗体或报表)
    D365: 笔记(现有量增加批号表字段查询条件)
    D365: 新功能(二)采购发票自动化流程
    D365: 新功能(一)按日期设置编号规则
    ES6 入门教程(未完)
    深入理解TypeScript(未完)
    项目
    vue + threejs 项目踩坑总结
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3438333.html
Copyright © 2011-2022 走看看