折半查找专场———有序数组的查找———————————————————————————————
题目描述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; }