数字在排序数组中出现的次数
时间限制:1 秒内存限制:32 兆特殊判题:否
- 题目描述:
- 统计一个数字在排序数组中出现的次数。
- 输入:
-
每个测试案例包括两行:
第一行有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
方案:
1、对于每一个需要查找的数在排好序数组中二分查找,如果存在,定位好之后向前向后查找出现个数,否则为0个;但是,当有很多的相等的数出现,而且查找数也刚好是查找那些出现了很多次的数时,算法时间复杂度将会退化。极端想,每个数都是相同的,查找的也是相同的,则算法复杂度为:O(nm)
2、使用二分查找思想,寻找出上界和下界,计算上下界之间的距离,即得出现的个数。这样可以避免了1中描述出现的问题。
3、如果是hash_map等之类的数据结构呢?
1 #include<stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <stdlib.h> 5 6 using namespace std; 7 8 int b_s(int a[], int n, int key) 9 { 10 int i, j, mid; 11 12 i = 0; 13 j = n-1; 14 15 while(i<=j) 16 { 17 mid = (i+j)/2; 18 if (a[mid] == key) 19 { 20 return mid; 21 } 22 else if (a[mid] > key) 23 { 24 j = mid -1; 25 } 26 else 27 { 28 i = mid +1; 29 } 30 } 31 32 return -1; 33 } 34 35 int main() 36 { 37 int n; 38 int i,tmp, k, j, cnt; 39 40 int *a; 41 int m; 42 43 44 while(scanf("%d",&n)==1) 45 { 46 a = (int *)malloc(sizeof(int)*n); 47 for (i=0; i<n; i++) 48 { 49 scanf("%d", &a[i]); 50 } 51 52 scanf("%d", &m); 53 54 for (i=0; i<m; i++) 55 { 56 scanf("%d", &tmp); 57 k = b_s(a, n, tmp); 58 if (k == -1) 59 { 60 printf("0\n"); 61 continue; 62 } 63 j = k-1; 64 cnt = 1; 65 while(j>=0 && a[j]==tmp) 66 { 67 cnt++; 68 --j; 69 } 70 j = k+1; 71 while(j<n && a[j]==tmp) 72 { 73 cnt++; 74 ++j; 75 } 76 printf("%d\n", cnt); 77 } 78 free(a); 79 } 80 81 82 83 return 0; 84 }
毕