一、题目描述

JZ37数字在升序数组中出现的次数
题目大意:找到指定数字在升序数组中出现的次数
注意审题:升序数组

二、算法1(暴力遍历)

算法思路

1.总体思路:直接遍历一次数组,当遇到指定数字时计数即可
2.这种方法虽然直观,但是并没有用上题目中提供的升序这一信息,因此一般不是最优解

代码实现(C++11)

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        int ans = 0;
        for(auto & d : data) ans += d == k;
        return ans;
    }
};

时间复杂度:O(n)
空间复杂度:O(1)

三、算法2(二分法)

算法思路

1.总体思路:由于题目给出的数组是升序的,因此我们可以联系到一种高效的查找算法--二分法
2.对于一段出现在数组中的指定数字,我们只要确定的它出现的第一个位置的下标l,和最后一个位置的下标r,即可得到它的长度为r - l + 1
3.实现细节:需要理解两种常用的二分模板,求大于等于x的第一个数的位置和求小于等于x的第一个数的位置

代码实现(C++11)

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        if(data.empty()) return 0;
        int l, r;
        int i = 0, j = data.size() - 1;
        // 确定l的位置
        while(i < j){
            int mid = i + j >> 1;
            if(data[mid] >= k) j = mid;
            else i = mid + 1;
            }
        l = i;
        if(data[l] < k) l++;    // 若不满足data[l] >= k, l++

        // 确定r的位置
        i = 0, j = data.size() - 1;
        while(i < j){
            int mid = i + j + 1 >> 1;
            if(data[mid] <= k) i = mid;
            else j = mid - 1;
            }
        r = i;
        if(data[r] > k) r--;    // 若不满足data[r] <= k, r--

        return r - l + 1;
    }
};

时间复杂度:O(logn)
空间复杂度:O(1)