在排序數組中查找數字---二分法

面試題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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章