在排序数组中查找数字---二分法

面试题53-1:统计一个数字在排序数组中出现的次数。

二分法查找

解法一:二分法的变形

  • (1) 递归
class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        if(data.empty())
            return 0;
        int low = 0, high = data.size() - 1;
        int FirstK = BinarySearchFirstK(data, low, high, k);
        int FinalK = BinarySearchFinalK(data, low, high, k);
        
        int TimeOfK = 0;
        if(FirstK > -1 && FinalK > -1) //每次使用一个变量前应该都要考虑其合法性
           TimeOfK  = FinalK - FirstK + 1;
        return TimeOfK;
    }
    
     //二分法查找第一个K的下标,递归写法
    int BinarySearchFirstK(vector<int>& data,int low,int high,int k){
       if(low <= high){
            int mid = (high + low) >> 1;
            if(data[mid] == k){    
                if(mid == 0 || data[mid - 1] != k)
                    return mid;
                else
                    return BinarySearchFirstK(data, low, mid - 1, k);
                //return (mid == 0 || data[mid - 1] != k) ? mid : BinarySearchFirstK(data, low, mid - 1, k);
            }
            if(data[mid] > k)
                return BinarySearchFirstK(data, low, mid - 1, k);
            if(data[mid] < k)
                return BinarySearchFirstK(data, mid + 1,high, k);
        }
        return -1;
    }
    
     //二分法查找最后一个K的下标,递归写法
    int BinarySearchFinalK(vector<int>& data,int low,int high,int k){
       if(low <= high){
            int mid = (high + low) >> 1;
            if(data[mid] == k)    
                return (data.size()-1 == mid || data[mid + 1] != k) ? mid : BinarySearchFinalK(data, mid + 1, high, k);
            if(data[mid] > k)
                return BinarySearchFinalK(data, low, mid - 1, k);
            if(data[mid] < k)
                return BinarySearchFinalK(data, mid + 1,high, k);
        }
        return -1;
    }
};

  • (2)循环
//二分法循环
class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        if(data.empty())
            return 0;
        int low = 0, high = data.size() - 1;
        int FirstK = BinarySearchFirstK(data, low, high, k);
        int FinalK = BinarySearchFinalK(data, low, high, k);
        
        int TimeOfK = 0;
        if(FirstK > -1 && FinalK > -1) //每次使用一个变量前应该都要考虑其合法性
           TimeOfK  = FinalK - FirstK + 1;
        return TimeOfK;
    }
    
     //二分法查找第一个K的下标,循环写法
    int BinarySearchFirstK(vector<int>& data,int low, int high, int k){
       while(low <= high){
            int mid = (high + low) >> 1;
           if(data[mid] == k){    
               if(mid == 0 || data[mid - 1] != k)
                   return mid;
               else
                   high = mid - 1;
           }
            if(data[mid] > k)
                high = mid - 1;
            if(data[mid] < k)
                low = mid + 1;
        }
        return -1;
    }
    
     //二分法查找最后一个K的下标,循环写法
    int BinarySearchFinalK(vector<int>& data,int low,int high,int k){
       while(low <= high){
            int mid = (high + low) >> 1;
            if(data[mid] == k)    
                if(data.size()-1 == mid || data[mid + 1] != k)
                   return mid;
               else
                   low = mid + 1;
            if(data[mid] > k)
                high = mid - 1;
            if(data[mid] < k)
                low = mid + 1;
        }
        return -1;
    }
};

解法二:STL二分查找算法

#if 1
//STL:equal_range() 可以找出有序序列中所有和给定元素相等的元素。
class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        auto resultPair = equal_range(data.begin(), data.end(),k);
        return resultPair.second - resultPair.first;
    }
};

#elif 0
//STL:第一个大于目标值的坐标 减去 第一个等于目标值的坐标
class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        return upper_bound(data.begin(), data.end(), k) - lower_bound(data.begin(), data.end(), k);
    }
};
#endif

面试题53 - II. 0~n-1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        //if(nums.empty()) return -1;  //包含在最后一句中
        int low = 0, high = nums.size()-1;
        while(low <= high){
            int mid = (low + high) >> 1;
            if(nums[mid] == mid) //下标和值相等
                low = mid + 1;
            if(nums[mid] != mid){ //下标和值不相等
                if(mid == 0 || nums[mid - 1 ] == mid - 1)
                    return mid;     //循环出口
                if(nums[mid - 1 ] != mid - 1)
                    high = mid - 1;
            }
        }

    //到这一步,说明前面数字都不缺了,那只能是少最后一个数
    if(low == nums.size())
        return nums.size();
    // 无效的输入,比如数组不是按要求排序的,数组为空
    // 或者有数字不在0到n-1范围之内(没有缺失的)
    return -1;
    }
};
发布了68 篇原创文章 · 获赞 26 · 访问量 3952

猜你喜欢

转载自blog.csdn.net/weixin_43892514/article/details/104925110
今日推荐