数字在排序数组中出现的次数

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

这个题思路有两种,

一:直接遍历数组统计,时间复杂度为O(n)略

二:利用二分法的变种来写

思路:

/* 思路, 和普通的二分改变的是当等于给定值需要修改
我们对数组data进行二分,如果数组中间的数字小于k,说明k应该出现在中间位置的右边;
如果数组中间的数字大于k,说明k应该出现在中间位置的左边;
如果数组中间的数字等于k,并且中间位置的前一个数字不等于k,
说明这个中间数字就是数字k出现的第一个位置。
*/

代码:

class Solution {
public:
    // 二分思路,先找出第一个出现的,在找出最后一个出现的。两个下标相减就是
    // 涉及到二分查找的变种
    int GetNumberOfK(vector<int> data ,int k) {
        int len = data.size();
        if (len <= 0)
            return 0;
        int first = GetFirstK(data, k, 0, len-1);
        int last  = GetLastK(data, k, 0, len-1);
        if (first != -1 && last != -1)
            return last-first + 1;
        else
            return 0;
    }
    //找到第一个出现的位置
    int GetFirstK(vector<int> data, int k, int left, int right)
    {
        while(left <= right)
        {
            int mid = left + (right-left)/2;
            if (data[mid] > k)  //在左半区
                right = mid -1;
            else if (data[mid] < k) // 在右半区
                left = mid + 1;
            else
            {
                if (mid == 0 || data[mid-1] != k)
                    return mid;
                else  //还要向左半区找
                    right = mid - 1;
            }
        }
        return -1;
    }
    // 找到最后一个出现的位置
    int GetLastK(vector<int> data, int k, int left, int right)
    {
        while(left <= right)
        {
            int mid = left + (right-left)/2;
            if (data[mid] > k)  //在左半区
                right = mid -1;
            else if (data[mid] < k) // 在右半区
                left = mid + 1;
            else
            {
                if (mid == data.size()-1 || data[mid+1] != k)
                    return mid;
                else  //还要向右半区找
                    left = mid + 1;
            }
        }
        return -1;
    }

};

 

含有main函数的

#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
    // 二分思路,先找出第一个出现的,在找出最后一个出现的。两个下标相减就是
    // 涉及到二分查找的变种
    int GetNumberOfK(vector<int> data ,int k) {
        int len = data.size();
        if (len <= 0)
            return 0;
        int first = GetFirstK(data, k, 0, len-1);
        int last  = GetLastK(data, k, 0, len-1);
        if (first != -1 && last != -1)
            return last-first + 1;
        else
            return 0;
    }
    //找到第一个出现的位置
    int GetFirstK(vector<int> data, int k, int left, int right)
    {
        while(left <= right)
        {
            int mid = left + (right-left)/2;
            if (data[mid] > k)  //在左半区
                right = mid -1;
            else if (data[mid] < k) // 在右半区
                left = mid + 1;
            else
            {
                if (mid == 0 || data[mid-1] != k)
                    return mid;
                else  //还要向左半区找
                    right = mid - 1;
            }
        }
        return -1;
    }
    // 找到最后一个出现的位置
    int GetLastK(vector<int> data, int k, int left, int right)
    {
        while(left <= right)
        {
            int mid = left + (right-left)/2;
            if (data[mid] > k)  //在左半区
                right = mid -1;
            else if (data[mid] < k) // 在右半区
                left = mid + 1;
            else
            {
                if (mid == data.size()-1 || data[mid+1] != k)
                    return mid;
                else  //还要向右半区找
                    left = mid + 1;
            }
        }
        return -1;
    }

};


int main()
{
    Solution s;
    vector<int> vec = {1,5,5,5,5,6};
    cout << s.GetNumberOfK(vec, 5);
    return 0;
}
// 对整个数组遍历
//    int GetNumberOfK(vector<int> data ,int k) {
//      int len = data.size();
//      if (len <= 0)
//            return 0;
//      int times = 0;
//      for (auto it = data.begin(); it != data.end(); it++)
//      {
//          if (*it == k)
//                ++times;
//      }
//        return times;
//    }
View Code

 

 

二分法变种

 

https://www.cnblogs.com/xiaokang01/p/12450117.html

posted @ 2020-03-09 18:10  Lucky&  阅读(208)  评论(0编辑  收藏  举报
//返回顶部开始
//返回顶部结束