LeetCode 704
题目链接: 704.二分查找
想要弄明白二分查找法,就要处理好两个边界:
//第一个边界,while循环里我们应该用 < 还是 <= 呢
while(left <= right)
while(left < right)
//第二个边界,当 target < nums[middle]时,我们调整 right 时用 middle 还是 middle - 1
if(target < nums[middle])
right = middle;
right = middle - 1;
当我们一开始确定好数组边界之后,就不要去改变这个边界,在后边处理时一直保持就好了。总结,就是下边一句话:
区间不变量,要在二分查找的过程中,保持不变量。
接下来先采用左闭右闭(其实就是,left和right下标都指向数组中的元素)写法讲解:
左闭:left = 0
右闭:right = nums.length - 1
这种情况下:while循环里 left 是可以 等于 right 的,因为它们都是指向数组里存在的元素。
while(left <= right)
现在采用左闭右开(这个时候right就不指向,数组内的元素了):
左闭:left = 0
右开:right = nums.length
我们可以看到,right指向了数组外边。所以,采用二分查找时 left 不能等于 right (因为 right 不指向数组中的元素)
while( left < right)
接下来处理第二个边界:
当target < nums[middle]
时,我们要调整 right 。
我们采用右闭区间时:
right要指向,下次查找区间内。middle已经判断过了,所以不在下次查找区间内。
right = mid - 1;//所以,调整 right = middle - 1;
我们采用右开区间时:
right要指向,下次查找区间外边。middle已经判断过了,所以 middle 在下次查找区间外。
right = mid;//所以,调整 right = middle;
(左闭右闭类):
class Solution {
public int search(int[] nums, int target) {
int left= 0,right= nums.length - 1,mid = 0;
while(left <= right){
mid = left + ((right - left) >> 1);//防止两个int型相加溢出,这行代码含义是 小的数 加上 与大数的差值的一半。就是两数相加除以二。
if(nums[mid] < target){
left = mid + 1;
}else if(nums[mid] > target){
right = mid - 1;
}else if(nums[mid] == target){
return mid;
}
}
return -1;
}
}
27.移除元素
在本子上画了一遍大概过程,按着过程经过几次错误之后,两层循环解出来了。
class Solution {
public int removeElement(int[] nums, int val) {
int size = nums.length;
for(int i = 0; i < size;i++){
if(nums[i] == val){
for(int j = i +1;j<size;j++){
nums[j-1] = nums[j];
}
i--;
size--;
}
}
return size;
}
}
其中i--
是因为你把后边的数字往前提了,循环最后会i++
这样的话我们会跳过刚移到前边覆盖位置的元素,没有判断。所以,要i--
。有人疑惑如果第一个就是要移除的值i--
使下一轮i = -1
。不会因为在本次循环结束会i++
。所以,下一轮开始依旧是i = 0
。
在看完代码随想录的解法,感觉好神奇。因为,题目不要求移除完的数组还是按照以前的顺序。所以可以用快慢指针法。
快慢指针法
代码如下:
class Solution {
public int removeElement(int[] nums, int val) {
int size = nums.length, fastIndex = 0,slowIndex = 0;
for(;fastIndex <nums.length ;fastIndex++){
if(val != nums[fastIndex]){
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
这个方法的大概过程是,当有要消除的值slowIndex会慢1个位置,当fastIndex走到最后时,slow的位置就是剩余的数组元素的个数。有目标元素的话就把后边的非目标元素换上去。