704
当数组中元素是唯一时。
每次划分区间,每次形成两个区间和一个mid。
如果mid != target,那么target一定在左区间或者是右区间。
不断的进行划分,缩小搜索区间,最终找到target。
体现在代码中,需要注意的点:
①left/right的初始值(想清楚区间的定义)
right = nums.length;//左闭右开
right = nums.length - 1;//左闭右闭
②while中的条件
循环的退出条件是当搜索区间为空时,不再划分区间。
left <= right
left < right
//与上面不是一一对应
③每一次划分的过程中,left和right应该如何移动
值唯一可能不太能体现思想。
mid已经搜索过了,再去分别搜索[left,mid-1]和[mid+1,right]。
right = mid - 1 还是 right = mid;
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while(left <= right){
int mid = left + (right-left)/2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] > target){//说明目标在左半区间
right = mid - 1;
}else if(nums[mid] < target){//说明目标在左半区间
left = mid + 1;
}
}
return -1;
}
}
左闭右开的写法:
如果说定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,那么二分法的边界处理方式则截然不同。
有如下两点:
- while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
- if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
27
暴力解法:
class Solution {
public int removeElement(int[] nums, int val) {
//计数器
int count = 0;
int len = nums.length;
//从后往前依次检查每一个元素,是否是val
for(int i=len-1;i>=0;i--){
if(nums[i] == val){//找到需要移除的元素
for(int j=i;j<len-1-count;j++){
nums[j] = nums[j+1];
}
count++;
}
}
return len-count;
}
}