1. 剑指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整数,表示数组中该数字出现的次数。
样例输入:
  1. 8
  2. 1 2 3 3 3 3 4 5
  3. 1
  4. 3
样例输出:
  1. 4
  1. 题意分析:
      题目要求在一个数组中找出一个数出现的次数,
        第一种想法,当然是一次性全部数一遍,用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. //
  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 <= ){
  11. return -;
  12. }
  13.  
  14. if(target < a[] || target > a[n - ]){
  15. return -;
  16. }
  17.  
  18. // guarantee that a[left] < target && a[right] >= target
  19. if(target == a[]){
  20. return ;
  21. }
  22.  
  23. ll = ;
  24. rr = n - ;
  25. while(rr - ll > ){
  26. mm = (ll + rr) / ;
  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 -;
  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 <= ){
  46. return -;
  47. }
  48.  
  49. if(target < a[] || target > a[n - ]){
  50. return -;
  51. }
  52.  
  53. // guarantee that a[left] <= target && a[right] > target
  54. if(target == a[n - ]){
  55. return n - ;
  56. }
  57.  
  58. ll = ;
  59. rr = n - ;
  60. while(rr - ll > ){
  61. mm = (ll + rr) / ;
  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 -;
  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) == ){
  84. if(n <= ){
  85. continue;
  86. }
  87. a = new int[n];
  88. for(i = ; i < n; ++i){
  89. scanf("%d", &a[i]);
  90. }
  91. scanf("%d", &m);
  92. for(i = ; i < m; ++i){
  93. scanf("%d", &target);
  94. ll = bsearch_left(a, n, target);
  95. if(ll < ){
  96. printf("0\n");
  97. continue;
  98. }
  99. rr = bsearch_right(a, n, target);
  100. if(rr < ){
  101. printf("0\n");
  102. continue;
  103. }
  104. if(rr >= ll){
  105. printf("%d\n", rr - ll + );
  106. }else{
  107. printf("0\n");
  108. }
  109. }
  110. delete[] a;
  111. a = NULL;
  112. }
  113.  
  114. return ;
  115. }

剑指Offer - 九度1349 - 数字在排序数组中出现的次数的更多相关文章

  1. 剑指offer(37)数字在排序数组中出现的次数。

    题目描述 统计一个数字在排序数组中出现的次数. 题目分析 这题用暴力解也可以过,不过面试官肯定期待更好的解法. 查找我们最熟悉的就是二分查找了,不过二分查找查找的数在数组中只有一个,我们这里却有很多个 ...

  2. 剑指offer三十七之数字在排序数组中出现的次数

    一.题目 统计一个数字在排序数组中出现的次数. 二.思路 解法一:遍历数组计数 解法二:考虑到时有序数组,所以采用分查找,找到第一个K 和 最后一个K的位置, 二者相减. 三.代码 解法一: publ ...

  3. 【剑指Offer】37、数字在排序数组中出现的次数

      题目描述:   统计一个数字在排序数组中出现的次数.例如,输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于数字3在该数组中出现了4次,所以函数返回4.   解题思路:   既然输入的数 ...

  4. 【剑指offer】题目38 数字在排序数组中出现的次数

    思路: 应该是用二分查找分别找到该数字第一次和最后一次出现的位置,相减即可.O(logn) int findLeft(int a[], int n, int num) { , r = n - ; wh ...

  5. 剑指offer37:统计一个数字在排序数组中出现的次数

    1 题目描述 统计一个数字在排序数组中出现的次数. 2 思路和方法 (1)查找有序数组,首先考虑使用二分查找,使时间复杂度为O(log n).更改二分查找的条件,不断缩小区间,直到区间头和区间尾均为k ...

  6. 九度OJ 1349 数字在排序数组中出现的次数 -- 二分查找

    题目地址:http://ac.jobdu.com/problem.php?pid=1349 题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数 ...

  7. 【Offer】[53-1] 【数字在排序数组中出现的次数】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 统计一个数字在排序数组中出现的次数.例如,输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出 ...

  8. 九度oj 1349 数字在排序数组中出现的次数

    原题链接:http://ac.jobdu.com/problem.php?pid=1349 二分.. #include<algorithm> #include<iostream> ...

  9. 【剑指Offer面试编程题】题目1349:数字在排序数组中出现的次数--九度OJ

    题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数组的大小.1<=n <= 10^6. 第二行有n个整数,表示数组元素,每个元素均 ...

随机推荐

  1. PHP 简单调用rest WebServices

    <?php $ch = curl_init("http://api.cachk.com:8185/Tech-Trans.esPOS4.PosService.UAT/rest/enqui ...

  2. sql:表中数据全部删除之后,重新插入时,从1开始增加

    数据库中设置了自增列,有时候需要清楚数据库从新录入数据.最常见的做法就是使用sql语句"delete 表明名"或是直接选中数据,然后删除数据.但是再次插入数据的时候,你就会发现自增 ...

  3. IIS7 http自动跳转到https(通过编辑Web.config实现)

    本文摘自:https://www.cnblogs.com/wxbug/p/7054972.html 1.下载安装URL重写模块:Microsoft URL Rewrite Module 32位:htt ...

  4. April 20 2017 Week 16 Thursday

    We are all in the gutter, but some of us are looking at the stars. 我们都生活在阴沟里,但仍有人仰望星空. In the past m ...

  5. 1923. Scary Politics (timus) (dfs) search

    http://acm.timus.ru/problem.aspx?space=1&num=1923 -- timus This is s problem about thd dfs and s ...

  6. Entity Framework 6事务回滚

    使用EF6你有新的事务处理可以使用类似于: 复制代码 using (var context = new PostEntityContainer()) { using (var dbcxtransact ...

  7. Uva 12299 带循环移动的RMQ(线段树)

    题目链接:https://vjudge.net/contest/147973#problem/C 题意:传统的RMQ是一个不变的数组a求区间最值.现在要循环移动(往前移动). 分析:求区间问题,很容易 ...

  8. sqlserver 使用小技巧总结

    1.  在数据库 查询中  在表名后面 加    英文字母,可以方便 查询 select a.name ,b.hobbynamefrom student as a, hobby as bwhere a ...

  9. MySQL与SQLServer的区别(一千条语句)

    ER图.分页.差异.Java连接MySQL SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset LIMIT 子句可以被用于强制 ...

  10. p2597 灾难

    我的思路 代码: #include<cstdio> #include<iostream> #include<algorithm> #include<vecto ...