思路:由于数组中已经排好序,因此马上能够想到用二分查找,可是二分查找只能查找到一个数,因此查完之后要向左向右去找出分别的第一个和最后一个k,而后获得次数,这样的复杂度为O(n),所以咱们须要改进一下,修改二分查找找出第一个数和最后一个数,就可使复杂度变成O(logN),如何判断第一个数呢,只要找到的这个数下标是0或者不为0,则与其左边数不同则就是第一个k了,若是不是找到第一个k,则继续找;如何判断最后一个数呢?只要找到这个数的下标是size()-1或者它的下一个数与它不相等,则说明是最后一个数,否则就继续找。
代码逐次改进web
int GetNumberOfK(vector<int> data ,int k) { //采用二分查找 if(data.size() == 0) return 0; int left = GetCore(data,0,data.size()-1,k,true); if(left == -1)return 0; int right = GetCore(data,left,data.size()-1,k,false); return right-left+1; } int GetCore1(vector<int>& data,int low,int high,int k){ int middle; while(low <= high){ middle = low + ((high - low)>>1); if(data[middle] == k && (middle == 0 || data[middle-1] != k)){ //开启找第一个k的判断 return middle; } if(data[middle] >= k) high = middle - 1; else low = middle + 1; } return -1; } int GetCore2(vector<int>& data,int low,int high,int k){ int middle; while(low <= high){ middle = low + ((high - low)>>1); /*if(data[middle] == k && (middle == 0 || data[middle-1] != k)){ //开启找第一个k的判断 return middle; }*/ if(data[middle] == k && (middle == data.size()-1 || data[middle+1] != k)){ //开启找最后一个k的判断 return middle; } if(data[middle] > k) high = middle - 1; else low = middle + 1; } return -1; }
能够把两个函数写成一个,而且能够把判断条件合并判断,逐次改进数组
int GetNumberOfK(vector<int> data ,int k) { //采用二分查找 if(data.size() == 0) return 0; int left = GetCore(data,0,data.size()-1,k,true); if(left == -1)return 0; int right = GetCore(data,left,data.size()-1,k,false); return right-left+1; } int GetCore(vector<int>& data,int low,int high,int k,bool less){ int middle; while(low <= high){ middle = low + ((high - low)>>1); if(less && data[middle] == k && (middle == 0 || data[middle-1] != k)){ //开启找第一个k的判断 return middle; } if(!less && data[middle] == k && (middle == data.size()-1 || data[middle+1] != k)){ //开启找最后一个k的判断 return middle; } if(data[middle] > k) high = middle - 1; else if(data[middle] == k && less) high = middle - 1; else low = middle + 1; /* if(less){ //若是当前是判断最小的 if(data[middle] >= k) high = middle - 1; else low = middle + 1; }else{ //若是当前是判断最大的 if(data[middle] > k) high = middle - 1; else low = middle + 1; }*/ } return -1; }
来源:力扣(LeetCode)
连接:https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof
著做权归领扣网络全部。商业转载请联系官方受权,非商业转载请注明出处。网络
整个数组都是递增有序的,而且缺失了一个数,咱们能够计算出这n个数的和为n(n-1)/2,而后再计算一次数组的和,而后差值就是缺失的数,可是这样的复杂度是O(n)。
由于这个数组是递增有序的,应该要想到二分查找,那数组有什么特色呢,缺失了一个数的话,那么缺失数以前的数与下标应该是同样的,缺失后的数与下标应该是相差1的,所以咱们应该能够修改一下二分查找使其找出第一个与下标不一致的数,下标就是缺失的数,那么如何判断呢,就是要么找到这个数下标是0否则它的前一个数应该是与下标同样的。less
class Solution { public: int missingNumber(vector<int>& nums) { //二分查找,找出第一个下标和数不一样的数 if(nums.size() == 0)return 0; int low = 0,high = nums.size()-1; int middle; while(low <= high){ middle = low + ((high - low) >> 1); if(nums[middle] != middle && (middle == 0 || nums[middle - 1] == middle - 1)) return middle; else if(nums[middle] == middle) low = middle+1; else high = middle-1; } return nums.size(); } };
能够采用顺序查找,可是其实递增的特性,所以要思考采用二分查找,找出其二分的规律,假设有一个数等于其下标,下一个数大于下标,那么大于下标的数以后的数一定都是大于下标的,若是有一个数小于下标,那么其左边的数一定也是小于下标的,所以能够依据下标与数之间的关系进行二分,而且若是要找出多个数一定是在相等的周围才有可能存在相等的数。ide
int getEqual(vector<int> data){ if(data.size() == 0) return -1; int low = 0,high = data.size()-1; int middle; while(low <= high){ middle = low +((high-low) >> 1); if(data[middle] == middle) return middle; else if(data[middle] > middle) high = middle - 1; else low = middle + 1; } return -1 ; }