九度 题目1349:数字在排序数组中出现的次数

题目来源: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值