题目一:数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{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;
}