1. 程式人生 > >(4)統計一個數字,在排序陣列中出現的次數

(4)統計一個數字,在排序陣列中出現的次數

題目描述:統計一個數字K,在排序陣列中出現的次數;

例如:陣列data{1,2,2,3,3,3,3,4} , k = 3 則其出現次數應該為4;

思路一

順序掃描,若data[i] = k , 計數Number ++;

時間複雜度為O(n);

思路二

耗費時間主要還是在查詢k上,由於陣列已經排好序,可以利用二分查詢演算法 , 進行查詢;若K= 3,又因為3連續出現;

故直觀的想法就是:如果知道第一個出現的k下標 和最後一個出現的k下標,就很容易知道k出現的次數;

二分查詢:middle , start , end ; middle = (start + end) / 2

若data[middle] = k , 並且 data[middle - 1] != k;;或者 data[middle] = k 且 middle = 0 , 此時那麼此時的middle 即為     k第一次出現的下標 

若data[middle] > k , 則 目標k在陣列的前半段,故--> end = middle - 1;

若data[middle] < k , 則目標k在陣列的後半段 , 故-->start = middle + 1;

程式碼實現:

#include<iostream>
using namespace std;
//-----------------------------------------------------------------------------------------------------------------
int GetFirstK(int* data, int length, int k, int start, int end);
int GetLastK(int* data, int length, int k, int start, int end);
//-----------------------------------------------------------------------------------------------------------------
//函式功能:查詢k在目標陣列data[]中的次數
int GetNumberOfK(int* data, int length, int k)
{
    int number = 0;

    if(data != NULL && length > 0)
    {
        int first = GetFirstK(data, length, k, 0, length - 1);
        int last = GetLastK(data, length, k, 0, length - 1);
        
        if(first > -1 && last > -1)
            number = last - first + 1;
    }

    return number;
}

// 找到陣列中第一個k的下標。如果陣列中不存在k,返回-1
//時間複雜度:O(logn)
int GetFirstK(int* data, int length, int k, int start, int end)
{
    if(start > end)
        return -1;

    int middleIndex = (start + end) / 2;
    int middleData = data[middleIndex];

    if(middleData == k)
    {
        if((middleIndex > 0 && data[middleIndex - 1] != k) 
            || middleIndex == 0)
            return middleIndex;
        else
            end  = middleIndex - 1;
    }
    else if(middleData > k)
        end = middleIndex - 1;
    else
        start = middleIndex + 1;

    return GetFirstK(data, length, k, start, end);
}

// 找到陣列中最後一個k的下標。如果陣列中不存在k,返回-1
//時間複雜度:O(logn)
int GetLastK(int* data, int length, int k, int start, int end)
{
    if(start > end)
        return -1;

    int middleIndex = (start + end) / 2;
    int middleData = data[middleIndex];

    if(middleData == k)
    {
        if((middleIndex < length - 1 && data[middleIndex + 1] != k) 
            || middleIndex == length - 1)
            return middleIndex;
        else
            start  = middleIndex + 1;
    }
    else if(middleData < k)
        start = middleIndex + 1;
    else
        end = middleIndex - 1;

    return GetLastK(data, length, k, start, end);
}