題目一:數字在排序數組中出現的次數
題目:統計一個數字在排序數組中出現的次數。例如輸入排序數組{1, 2, 3, 3, 3, 3, 4, 5}和數字3,由於3在這個數組中出現了4次,因此輸出4。
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
using namespace std;
int GetFirstK(int* data, int length, int k, int start, int end){ // 找到第一個k在數組中的下標, 不存在返回-1
if(start>end) return -1;
int midIndex=(start+end)/2;
int midData=data[midIndex];
if(midData==k){
if((midIndex>0 && data[midIndex-1]!=k) || midIndex==0){
return midIndex;
}else end=midIndex-1;
} else if(midData>k) end=midIndex-1;
else start=midIndex+1;
return GetFirstK(data, length, k, start, end);
}
int GetLastK(int* data, int length, int k, int start, int end){ // 找到最後一個k在數組中的下標, 不存在返回-1
if(start>end) return -1;
int midIndex=(start+end)/2;
int midData=data[midIndex];
if(midData==k){
if((midIndex<length-1 && data[midIndex+1]!=k) || midIndex==length-1) return midIndex;
else start=midIndex+1;
}else if(midData>k) end=midIndex-1;
else start=midIndex+1;
return GetLastK(data, length, k, start, end);
}
int GetNumberOfK(int* data, int length, int k){
int number=0;
if(data!=NULL && length>0){
int first=GetFirstK(data, length, k, 0, length-1);
int last=GetLastK(data, length, k, 0, length-1);
if(first>-1 && last>-1)
number=last-first+1;
}
return number;
}
int main() {
int data[]={1, 2, 3, 3, 3, 3, 4, 5};
printf("%d", GetNumberOfK(data, 8, 3));
return 0;
}
題目二:0~n-1 中缺失的數字。
題目:一個長度爲n-1的遞增排序數組中的所有數字都是唯一的,並且每個數字都在範圍0到n-1之內。在範圍0到n-1的n個數字中有且只有一個數字不在該數組中,請找出這個數字。
解決思路:
方法一:這個問題有一個直觀的解決方案。我們可以先用公式 n(n-1)/2 求出數字 0~n-1 的所有數字之後,接着求出數組中的所有數字的和,做差即可求出缺失值。時間複雜度O(n)
方法二:利用二分法查找,數字m和下標m對應。時間複雜度O(logn)
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
using namespace std;
int GetMissingNumber(const int* numbers, int length){
if(numbers==NULL || length<0) return -1;
int left=0, right=length-1;
while(left<=right){
int mid=(left+right)>>1;
if(numbers[mid]!=mid){ // 只要往左邊查找
if(mid==0 || numbers[mid-1]==mid-1) return mid;
right=mid-1;
}else left=mid+1; // 只要往右邊查找
}
if(left==length) return length;
// 無效的輸入, 比如數組不是按要求排序的, 或者有數字不在 0~n-1 範圍內
return -1;
}
int main() {
int data[]={0, 1, 2, 3, 4, 6, 7, 8, 9 ,10};
printf("%d", GetMissingNumber(data, 10));
return 0;
}
題目三:數組中數值和下標相等的元素。
題目:假設一個單調遞增的數組裏的每個元素都是整數並且是唯一的。請編程實現一個函數找出數組中任意一個數值等於其下標的元素。例如,在數組{-3, -1, 1, 3, 5}中,數字3和它的下標相等。
解決思路:
方法一:我們很容易就能想到最直觀的解法:從頭到尾依次掃描數組中的數字,並逐一檢驗數字是不是和下標相等。顯然,這種算法的時間複雜度是O(n)。
方法二:由於數組是單調遞增排序的,因此我們可以嘗試用二分查找算法來進行優化。
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
using namespace std;
int GetNumberSameAsIndex(const int* numbers, int length){
if(numbers==NULL || length<=0) return -1;
int left=0, right=length-1;
while(left<=right){
int mid=(left+right)>>1;
if(numbers[mid]==mid) return mid;
else if(numbers[mid]>mid) right=mid-1;
else left=mid+1;
}
return -1;
}
int main() {
int data[]={-3, -1, 1, 3, 5};
printf("%d", GetNumberSameAsIndex(data, 5));
return 0;
}