704:二分查找
题目链接:
704二分查找
视频
文字版
二分法特点:1)必须是有序
2)如有重复元素,返回值可能不唯一
文本区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。
两种情况,1)区间左闭右闭 2)左闭右开
易混淆点:1)while(left<right)还是while(left <= right)
2)if(num[middle] > target)
right=middle 还是 right= middle -1
第一种情况:区间左闭右闭
【1,1】
/*例如在【1,1】里寻找2
middle=(0+!)/2=0
num[0]=1<2,target在右半部分,修改左边界,
left=middle+1=1,此时right=1
left==right是有意义的
如果while的循环条件不包括等于号的话则不会判断num[1]的值是否是target
所以循环条件里必+=
*/
/*
若在修改边界条件时不+1或-1,则会把已经判断过的num[middle]包含在新的判断区间里,是无用功
*/
left=0;
right =num.size -1;
middle= (left + right) / 2
while(left <= right)
{
if (num[middle]>target)
right= middle-1;
else if( num[middle] < target )
left= middle+1;
else
return middle;
}
return -1;
java版本:
在编写时犯了一处错误,middle的计算放在了循环外
第一个if避免了当 target 小于nums[0] nums[nums.length - 1]时多次循环运算,提高了效率
class Solution {
public int search(int[] nums, int target) {
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
int left=0;
int right=nums.length-1;
while(left<=right){
int middle = left + ((right-left)>>1);
if(nums[middle]<target)
left=middle+1;
else if(nums[middle]>target)
right=middle-1;
else
return middle;
}
return -1;
}
}
第二种情况:区间左闭右开
eg.[1,1)
区间既包含1,又不包含1,不合法
left和right相等的情况在这个区间无意义
即搜索区间永远不会包含right
left=0;
right =num.size;//第一处不同
middle= (left + right) / 2
while(left < right)//第二处不同
{
if (num[middle]>target)
right= middle;//第三处不同,仍是左闭右开
else if( num[middle] < target )
left= middle+1;
else
return middle;
}
return -1;
class Solution {
public int search(int[] nums, int target) {
if(target<nums[0] || nums[nums.length-1]<target)
return -1;
int left=0,right=nums.length;
while(left<right){
int middle=left +((right-left)>>1);
if(nums[middle]>target)
right=middle;
else if(nums[middle]<target)
left=middle+1;
else
return middle;
}
return -1;
}
}
总结:
定义了什么样的区间,决定了我们如何处理边界
在循环中坚持根据查找区间的定义来做边界处理
27:移除元素
27移除元素
视频
文字版
方法一:暴力解法
两层for循环,第一层遍历,第二层把后面的元素覆盖到前一个元素上
方法二:快慢指针
复杂度O(n)
快指针代表新数组中的元素,慢指针代表新数组中需要更新的位置
slow = 0;
for( fast=0; fast< num.size;fast ++)
{
if(num[fast]!=val)
{
num[slow++]=num[fast];
}
}
return slow;//这里比较巧
class Solution {
public int removeElement(int[] nums, int val) {
int slow=0,fast=0;
for(;fast<nums.length;fast++){
if(nums[fast]!=val){
nums[slow++]=nums[fast];
}
}
return slow;
}
}