剑指offer|数字在排序数组中出现的次数

来源:互联网 发布:哪个搜索软件好 编辑:程序博客网 时间:2024/04/23 19:59

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

思路:

首先最直观的就是遍历一遍数组,统计一下给定的数字出现的次数。没想到这样也能通过,看来牛客网的oj不是很严格。

class Solution {public:    int GetNumberOfK(vector<int> data ,int k) {        int count=0;        if(data.empty())            return count;        for(int i=0; i<data.size();++i)            if(data[i] == k)                ++count;        return count;    }};

然后想到这是一个排序数组,如果数字出现的话只会连续出现,所以当遍历到该数之后第一个不是该数字的元素时就可以结束遍历啦。再次通过。

class Solution {public:    int GetNumberOfK(vector<int> data ,int k) {        int count=0;//记录k出现的次数        int occur=0;//记录k是否出现过        if(data.empty())            return count;        for(int i=0; i<data.size();++i)        {          if(occur==1 && data[i]!= k)//如果k出现过且当前元素不等于k则结束循环              break;          if(data[i] == k)            {                ++count;                occur=1;            }         }        return count;    }};

然后又想到这样顺序寻找k也是很费时的,可以通过类似二分查找来定位k。再次通过。

class Solution {public:    int GetNumberOfK(vector<int> data ,int k) {        int count=0;        if(!data.empty())        {            int inx= binarySearch(data, k, 0, data.size()-1);            if(inx == -1)                return count;            int inxleft=inx;            int inxright=inx+1;            while(inxleft >=0 && data[inxleft] == k)            {                ++count;                --inxleft;            }            while(inxright<data.size() && data[inxright] ==k)            {                ++count;                ++inxright;            }        }        return count;    }    int binarySearch(vector<int> data,int k,int begin,int end)    {        if(begin == end)        {            if(data[begin]==k)                return begin;            else                return -1;        }        int mid=begin+(end-begin)/2;        if(data[mid]==k)            return mid;        else if(data[mid]<k)            return binarySearch(data, k, mid+1,end);        else            return binarySearch(data, k, begin, mid-1);    }};

再然后看剑指offer,书中指出我上面的算法时间复杂度是O(n).因为k有可能出现n次。
一种O(logn)时间复杂度的算法是:通过二分查找先找到第一个k的位置,再通过二分查找找到最后一个k的位置。最后两个位置相减就出来了。

class Solution {public:    int GetNumberOfK(vector<int> data ,int k) {        int count=0;        if(data.empty())            return count;        int firstK=findFirstK(data, k, 0, data.size()-1);        int lastK=findLastK(data, k, 0, data.size()-1);        if(firstK != -1 && lastK != -1)        {            count=lastK-firstK+1;        }        return count;    }    int findFirstK(vector<int> data,int k,int begin,int end)    {        if(begin >end)            return -1;        int mid=(end+begin)/2;        if(data[mid]==k)        {            if((mid>0 && data[mid-1] !=k) || mid==0)                return mid;            else                end=mid-1;        }        else        {            if(data[mid]>k)                end=mid-1;            else                begin=mid+1;        }        return findFirstK(data,k,begin,end);    }    int findLastK(vector<int> data, int k, int begin,int end)    {        if(begin>end)            return -1;        int mid=begin +(end-begin)/2;        if(data[mid]== k)        {            if( (mid<data.size()-1 && data[mid+1] != k)  || mid==data.size()-1)                return mid;            else                begin=mid+1;        }        else        {            if(data[mid]>k)                end=mid-1;            else                begin=mid+1;        }        return findLastK(data,k,begin,end);    }    };
0 0
原创粉丝点击