面試題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;
}
};