剑指offer面试题38:数字在排序数组中出现的次数

题目描述:统计一个数字在排序数组中出现的次数。输入:

每个测试案例包括两行:

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

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

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

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

输出:

对应每个测试案例,有m行输出,每行1整数,表示数组中该数字出现的次数。

样例输入:81 2 3 3 3 3 4 513样例输出:4

题目分析:

数字在排序数组中出现的次数,第一想法应该是用hash方法,计算出数组中所有数据出现的次数,,然后直接查找,时间复杂度O(n),空间复杂度O(n)。但是这种方法未能利用该数组是排序的特点,所以有关排序的题目,要及时联想到二分查找。

本题就是利用的二分查找的一个变体,来求出要查找的数在数组中第一次出现和最后一次出现的位置,来确定数字在数组中出现的次数。

当然在具体写程序的过程还要注意一些临界条件的判断以及特殊情况的处理(如某个数出现的位置是0和在数组中未找到这个数字返回为0的时候区别,我程序中用了标记来区分这两种情况)。二分查找时间复杂度是O(logn),减少了时间复杂度。

//source:?pid=1349#include <iostream>#include <cstdio>using namespace std;bool flag1 = true;bool flag2 = true;int SearchFirst(int A[], int n, int value){int left = 0, right = n – 1;while (left <= right){int mid = (left + right)/2;if (A[mid] < value)left = mid + 1;else if (A[mid] > value)right = mid – 1;else{if (A[mid – 1] != value || mid == 0)//mid==0return mid;elseright = mid – 1;}}flag1 = false;return 0;}int SearchLast(int A[],int n, int value){int left = 0, right = n – 1;while (left <= right){int mid = (left + right)/2;if (A[mid] < value)left = mid + 1;else if (A[mid] > value)right = mid – 1;else{if (A[mid + 1] != value || mid == n)//mid==nreturn mid;elseleft = mid + 1;}}flag2 = false;return 0;}int main(){int n, m;//n是数组的大小,m是查询的次数int k;//要查询的数while (scanf("%d",&n)!=EOF){int *array = new int[n+1];for (int i = 0; i < n; i++){scanf("%d", array+i);}scanf ("%d",&m);while (m–){scanf("%d",&k);int first =SearchFirst(array,n,k);int last = SearchLast(array,n,k);if (!flag1 && !flag2)printf("0\n");elseprintf("%d\n",last – first + 1);}}return 0;}

我只愿,在你的理想和希望里能为你增加一点鼓励,

剑指offer面试题38:数字在排序数组中出现的次数

相关文章:

你感兴趣的文章:

标签云: