剑指offer-38 统计一个数字在排序数组中出现的次数

来源:互联网 发布:知鱼水族花园怎么用 编辑:程序博客网 时间:2024/06/08 17:01
#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;int GetFirstK(int* data,int length,int target,int start,int end);int GetLastK(int* data,int length,int target,int start,int end);int GetCountOfK(int * data,int length,int target);/*统计一个数字在排序数组中出现的次数排序,联想到二分法如果能利用二分法找到目标数字第一个出现的下标和最后一个出现的下标那么就可以知道次数了*//*返回目标数字第一次出现的下标时间复杂度 O(logn)*/int GetFirstK(int* data,int length,int target,int start,int end){    if(start > end)        return -1;    int midIndex = (start+end)/2;    int midData = data[midIndex];    if(midData==target)    {        if((midIndex > 0 && data[midIndex-1] != target) || midIndex==0)            return midIndex;        else            end = midIndex-1;    }    else if(midData>target)        end = midIndex-1;    else        start = midIndex +1;    return GetFirstK(data,length,target,start,end);}/*返回目标数字最后出现的下标时间复杂度 O(logn)*/int GetLastK(int* data,int length,int target,int start,int end){    if(start > end)        return -1;    int midIndex = (start+end)/2;    int midData = data[midIndex];    if(midData==target)    {        if((midIndex < length-1 && data[midIndex+1] != target) || midIndex==length-1)            return midIndex;        else            start = midIndex+1;    }    else if(midData<target)        start = midIndex+1;    else        end = midIndex -1;    return GetLastK(data,length,target,start,end);}/*找到了第一次出现的下标和最后一次出现的下标,那么出现次数为last-first+1*/int GetCountOfK(int * data,int length,int target){    int result = 0;    if(data !=NULL && length > 0)    {        int first = GetFirstK(data,length,target,0,length-1);        int last = GetLastK(data,length,target,0,length-1);        if(first > -1 && last >-1)            result = last-first +1;    }    return result;}void Test(char* testName, int data[], int length, int k, int expected){    if(testName != NULL)        printf("%s begins: ", testName);    int result = GetCountOfK(data, length, k);    if(result == expected)        printf("Passed.\n");    else        printf("Failed.\n");}// 查找的数字出现在数组的中间void Test1(){    int data[] = {1, 2, 3, 3, 3, 3, 4, 5};    Test("Test1", data, sizeof(data) / sizeof(int), 3, 4);}// 查找的数组出现在数组的开头void Test2(){    int data[] = {3, 3, 3, 3, 4, 5};    Test("Test2", data, sizeof(data) / sizeof(int), 3, 4);}// 查找的数组出现在数组的结尾void Test3(){    int data[] = {1, 2, 3, 3, 3, 3};    Test("Test3", data, sizeof(data) / sizeof(int), 3, 4);}// 查找的数字不存在void Test4(){    int data[] = {1, 3, 3, 3, 3, 4, 5};    Test("Test4", data, sizeof(data) / sizeof(int), 2, 0);}// 查找的数字比第一个数字还小,不存在void Test5(){    int data[] = {1, 3, 3, 3, 3, 4, 5};    Test("Test5", data, sizeof(data) / sizeof(int), 0, 0);}// 查找的数字比最后一个数字还大,不存在void Test6(){    int data[] = {1, 3, 3, 3, 3, 4, 5};    Test("Test6", data, sizeof(data) / sizeof(int), 6, 0);}// 数组中的数字从头到尾都是查找的数字void Test7(){    int data[] = {3, 3, 3, 3};    Test("Test7", data, sizeof(data) / sizeof(int), 3, 4);}// 数组中的数字从头到尾只有一个重复的数字,不是查找的数字void Test8(){    int data[] = {3, 3, 3, 3};    Test("Test8", data, sizeof(data) / sizeof(int), 4, 0);}// 数组中只有一个数字,是查找的数字void Test9(){    int data[] = {3};    Test("Test9", data, sizeof(data) / sizeof(int), 3, 1);}// 数组中只有一个数字,不是查找的数字void Test10(){    int data[] = {3};    Test("Test10", data, sizeof(data) / sizeof(int), 4, 0);}// 鲁棒性测试,数组空指针void Test11(){    Test("Test11", NULL, 0, 0, 0);}int main(){    Test1();    Test2();    Test3();    Test4();    Test5();    Test6();    Test7();    Test8();    Test9();    Test10();    Test11();    return 0;}


一、一般看到有序数组或者部分有序的数组,首先要考虑二分法

二、二分法的步骤是不断改变区间的大小,知道找到想要的值

三、要考虑各种临界值和边界情况


0 0
原创粉丝点击