折半查找专场———有序数组的查找———————————————————————————————
题目描述1
统计一个数字在
排序数组中出现的次数。
思路:通过折半查找找到k开始和结束的位置。O(logn)
class Solution {
public:
int GetFirstK(vector<int> data,int k,int start,int end){
//折半查找注意边界条件
if(start>end)
return -1;
int mid = (end+start)/2;
int midval = data[mid];
if(midval == k){
if(mid-1>=start&&data[mid-1]==k) //左侧还有k
end = mid-1;
else
return mid;
}
else if(midval > k)
end = mid-1;
else
start = mid+1;
return GetFirstK(data,k,start,end);
}
int GetLastK(vector<int> data,int k,int start,int end){
if(start>end)
return -1;
int mid = (end+start)/2;
int midval = data[mid];
if(midval == k)
{
if(mid+1<=end&&data[mid+1]==k) //右侧还有k
start = mid+1;
else
return mid;
}
else if(midval > k)
end = mid-1;
else
start = mid+1;
return GetLastK(data,k,start,end);
}
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty())
return 0;
int first = GetFirstK(data,k,0,data.size()-1);
int last = GetLastK(data,k,0,data.size()-1);
int number = 0;
if(first>-1&&last>-1)
number = last-first+1;
return number;
}
};
方法2:
//因为data中都是整数,所以可以稍微变一下,不是搜索k的两个位置,而是搜索k-0.5和k+0.5
//这两个数应该插入的位置,然后相减即可。
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
return biSearch(data, k+0.5) - biSearch(data, k-0.5) ;
}
private:
int biSearch(const vector<int> & data, double num){
int s = 0, e = data.size()-1;
while(s <= e){
int mid = (e - s)/2 + s;
if(data[mid] < num)
s = mid + 1;
else if(data[mid] > num)
e = mid - 1;
}
return s;
}
};
题目2:0到n-1中缺失的数字
描述:一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0到n-1之内。在范围0到n-1的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
思路:转化成下标与内容是否一致的问题,从左到右第一个不一致的位置的下标就是缺失的数,如果n-1个位置都一致,那缺失的就是最后一个数。
#include <cstdio>
#include<iostream>
#define nullptr NULL
using namespace std;
int GetMissingNumber(const int* numbers, int length)
{
//数的范围从0~n-1 按序选n-1个数放入n-1长的数组
//其中某一个位置开始下标和位置上的数不一致,返回下标即缺失的数。
if(!numbers||length<=0)
return -1;
int start = 0;
int end = length-1;
//该循环保证在n-1个位置上判定是否位置上的数与下标是否一致
//缺失的数 以下标形式返回
//没有判定当这n-1个位置上下标全一致 即缺失数N-1
while(start<=end)
{
int mid =(start+end)>>1;
if(numbers[mid]!=mid)
{
if(mid-1>=start&&numbers[mid-1]!=mid-1)
end = mid-1;
else
return mid; //mid=0或mid-1>=start时mid-1=numbers[mid-1];
}
else
start = mid+1;
}
//判定前n-1个数均没有缺失,缺失的是n-1这个数
if(start==length)
return length;
return -1;
}
题目3
// 面试题53(三):数组中数值和下标相等的元素
// 题目:假设一个单调递增的数组里的每个元素都是整数并且是唯一的。请编程实
// 现一个函数找出数组中任意一个数值等于其下标的元素。例如,在数组{-3, -1,
// 1, 3, 5}中,数字3和它的下标相等。
#include <cstdio>
#define nullptr NULL
int GetNumberSameAsIndex(const int* numbers, int length)
{
if(!numbers||length<=0)
return -1;
int start = 0;
int end = length-1;
while(start<=end){
int mid =(end+start)>>1;
if(numbers[mid]==mid)
return mid;
else if(numbers[mid]>mid)
end = mid-1;
else
start = mid+1;
}
return -1;
}