注意:前提是数组!!!数组是有序的 设容器为vector<int> nums; 查找的数字是 target
middle = left+(right-left)>>1
一、二分查找的边界问题
主要是因为对区间的定义没有想清楚,区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。
(1)右边界:
①初始:right=nums.size();循环条件:while(left<right) ;右边界确定时机:if(nums[middle]>target) right=middle
解释如下: 因为left最大值是nums.size()-1,right最大值nums.size() ,所以while循环条件left<right中没有等号;right = middle(之所以等于middle而不等于middle-1,是因为右边界确定时机:if(nums[middle]>target)已经取过middle(通过nums[middle]),但在下一次循环不能再取middle(通过nums[middle]),要不然 就是重复操作,在下一次循环的时候(left<right)注意是"<" 号 。left最大只会取到middle-1 而取不到middle)
②初始:right=nums.size()-1;循环条件:while(left<=right) ;右边界确定时机:if(nums[middle]>target) right=middle-1
解释如下: 因为left最大值是nums.size()-1,right最大值nums.size()-1 ,所以while循环条件left<=right中等号是成立的;right = middle-1(之所以是middle-1是因为这个middle在下一次循环的时候(left<=right)已经取过middle(通过nums[middle]),但在下一次循环不能再取middle而while条件是取到等号的。
(2)左边界:
if(nums[middle]<target) left++;
原因是已经取过nums[middle]不能重复取了,只能从nums[middle+1]开始比较。
二、力扣第35题
给定一个按照升序排列的整数数组 nums
,和一个目标值 target
。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target
,返回 [-1, -1]
。
进阶:实现时间复杂度为 O(log n)
示例 1:
- 输入: [1,3,5,6], 5
- 输出: 2
解析:题设已知:vector<int>& nums; l=0;r = nums.size();
做法:①判断是否有为空的情况,如果有返回(-1,-1)
②利用二分法先确定左边界的值
③判断左边界的索引值是否与目标值target相等,不等返回(-1,-1)
④利用二分法查找结束位置的值
步骤:
vector<int> res(2,-1); //设置(-1,-1)
①判断是否有为空的情况,如果有返回(-1,-1)
if(nums.empty()) return res;
②利用二分法确定左边界的值
while(l<r){ //注意这里的r=nums.size()-1 因为这个减一是排除nums中只含有一个元素的情况
int m=l+(r-l)/2;
if(nums[m]>=target) r=m;
else l=m+1;
}
if(nums[l]!=target) return res;//③判断值是否符合条件
res[0]=r; //②确定了左边界的值
④利用二分法查找结束位置的值
//首先确定右边界的值的范围是nums.size()
r=nums.size();
while(l<r){
int m=l+(r-l)/2;
if(nums[m]>target) r=m;
else l=m+1;
}
res[1]=l-1;
return res;
三、对于处理数据中的元素要用双指针法
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
int slowIndex = 0,fastIndex = 0;
for(fastIndex=0;fastIndex<nums.size();){
if(nums[slowIndex]!=nums[fastIndex]) num[slowIndex++]=nums[fastIndex];
fastIndex++;
}
力扣977
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100]
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i=0;i<nums.size();i++) nums[i]=nums[i]*nums[i];
vector<int> newNu(nums.size(),-1);
int l=0,k=nums.size()-1,r=nums.size()-1;
for(l=0;l<=r;){ //之所以有=号 是因为当两个指针指向同一个数据的时候也可以赋值
//如果没有 会导致最终结果首元素缺失
if(nums[l]<=nums[r]) newNu[k--]=nums[r--];
else newNu[k--]=nums[l++];
}
return newNu;
}
};