题目来源:http://ac.jobdu.com/problem.php?pid=1349
时间限制:1 秒
内存限制:32 兆
特殊判题:否
提交:1451
解决:432
-
题目描述:
- 统计一个数字在排序数组中出现的次数。
-
输入:
-
每个测试案例包括两行:
第一行有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
由于数组是排好顺序的,因此可以利用二分的思想找出重复k的第一个位置,以及最后一个位置,由此可以计算出K出现的次数。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1000010;
int GetkFirstPosition(int* arr, int k, int iStart, int iEnd)//找出重复k的第一个位置
{
if(iStart > iEnd)
return -1;
int iMid = (iStart + iEnd)>>1;
int iMidData = arr[iMid];
if(iMidData == k)
{
if((iMid > 0 && arr[iMid-1] != k) || iMid == 0)
return iMid;
else
iEnd = iMid-1;
}
else if(iMidData > k)
iEnd = iMid-1;
else
iStart = iMid+1;
return GetkFirstPosition(arr, k, iStart, iEnd);
}
int GetKEndPosition(int* arr, int n, int k, int iStart, int iEnd)//找出重复k的最后一个位置
{
if(iStart > iEnd)
return -1;
int iMid = (iStart + iEnd) >> 1;
int iMidData = arr[iMid];
if(iMidData == k)
{
if(((iMid < n-1) && arr[iMid+1] != k) || iMid == n-1)
return iMid;
else
iStart = iMid+1;
}
else if(iMidData < k)
iStart = iMid + 1;
else
iEnd = iMid - 1;
return GetKEndPosition(arr, n, k, iStart, iEnd);
}
int GetNumOfK(int* arr, int n, int k)//计算k出现次数
{
int iNum = 0;
int iStart, iEnd;
iStart = iEnd = 0;
if(arr != NULL && n > 0)
{
iStart = GetkFirstPosition(arr, k, 0, n-1);
iEnd = GetKEndPosition(arr, n, k, 0, n-1);
if(iStart > -1 && iEnd > -1)
iNum = iEnd - iStart + 1;
}
return iNum;
}
int main()
{
int arr[MAXN], i, n, m, iData;
while(~scanf("%d", &n))
{
for(i = 0; i < n; ++i)
scanf("%d", &arr[i]);
scanf("%d", &m);
while(m--)
{
scanf("%d", &iData);
int num = GetNumOfK(arr, n, iData);
printf("%d\n", num);
}
}
return 0;
}