面试题53:在排序数组中查找数字

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

解题思路

  • 二分查找+顺序遍历(O(n))
  • 二分查找变体

上代码(C++很香)

法二:二分查找变体

  首先,排序数组的查找,应该最先想到二分查找,能做到O(logn)的复杂度优势。然后,统计出现次数,如果用遍历前后的数量的方式,可能会达到O(n)的复杂度,所以,结合二分查找的变体,首先查找第一次出现的位置,然后查找最后一次出现的位置,两者作差即为次数。

  顺便复习一下二分查找与二分查找的变体。

  • 排序数组中第一次出现k的位置
  • 排序数组中最后一次出现k的位置
  • 排序数组中第一个大于等于k的位置
  • 排序数组中第一个小于等于k的位置
// 排序数组中第一次出现k的位置
int binarySearchFirst(vector<int> num, int k, int length){
    int low = 0;
    int high = length - 1;
    int middle = 0;
    while(low <= high){
        middle = low + ((high - low) >> 1);
        if(num[middle] == k){
            if(middle > 0 && num[middle - 1] != k || middle == 0)
                return middle;
            else
                high = middle - 1;
        }
        else if(num[middle] > k)
            high = middle - 1;
        else
            low = middle + 1;
    }
    return -1;
}

// 最后一次出现k的位置
int binarySearchLast(vector<int> num, int k, int length){
    int low = 0;
    int high = length - 1;
    int middle = 0;
    while(low <= high){
        middle = low + ((high - low) >> 1);
        if(num[middle] == k){
            if(middle < length - 1 && num[middle + 1] != k || middle == length - 1)
                return middle;
            else
                low = middle + 1;
        }
        else if(num[middle] > k)
            high = middle - 1;
        else
            low = middle + 1;
    }
    return -1;
}

int GetNumberOfK(vector<int> data ,int k) {
    // 首先查找第一次出现的位置
    int firstT = binarySearchFirst(data, k, data.size());
    if(firstT == -1)
        return 0;
    // 查找最后一次出现的位置
    int lastT = binarySearchLast(data, k, data.size());
    return lastT - firstT + 1;
}
posted @ 2020-08-21 23:28  程序员曾奈斯  阅读(193)  评论(0编辑  收藏  举报