二分查找法
视频讲解整理:
1.区间是左闭右开或者左闭右闭居多
2.左闭右闭
可以相等|middle-1
3.左闭右开
不能相等,所以不能用小于等于
right=middle
网站资料整理:
1.要求:题目的前提是数组为有序数组,同时题目还强调数组中无重复元素
2.左闭右闭:
- while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
- if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
class Solution {
public int search(int[] nums, int target) {
// 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
int left = 0, right = nums.length - 1;//长度减一
while (left <= right) {//可以小于等于
int mid = left + ((right - left) >> 1);//表示将前面计算得到的长度右移1位,
//相当于将长度除以2。位运算中的右移操作相当于对整数进行二进制表示向右移动一位,
//相当于除以2并取整。例如,对于值为5的整数,右移1位后得到2。
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;//因为右边取得到,所以可以直接加一
else if (nums[mid] > target)
right = mid - 1;
}
return -1;
}
}
3..左闭右开:
- while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
- if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length;
while (left < right) {//只能使用小于号,取不到右边
int mid = left + ((right - left) >> 1);
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid;//因为右边取不到,所以也不会再取mid了
}
return -1;
}
}
4.只是要明确每次收缩范围后 范围内的元素是哪些 注意会不会漏掉边界就好
5.
- 二分的最大优势是在于其时间复杂度是O(logn),因此看到有序数组都要第一时间反问自己是否可以使用二分。
-
写成 mid = l + (r - l) / 2或者 mid = l + ((r - l) >> 1) 可以避免溢出问题
- 对于二进制的正数来说,右移x位相当于除以2的x几次方,所以右移一位等于➗2,用位运算的好处是比直接相除的操作快
力扣704完成
删除元素
数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖
力解法的时间复杂度是O(n^2)
双指针法
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
-
class Solution { public int removeElement(int[] nums, int val) { // 快慢指针 int slowIndex = 0; for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) { if (nums[fastIndex] != val) { nums[slowIndex] = nums[fastIndex]; slowIndex++; } } return slowIndex; } }
力扣26 删除有序数组中的重复项
-
class Solution { public int removeDuplicates(int[] nums) { if(nums == null || nums.length == 0){ return 0; } int slowIndex = 0; for(int fastIndex = 1; fastIndex < nums.length; fastIndex++){ //fast的从1开始 if(nums[fastIndex]!= nums[slowIndex]){ slowIndex++; nums[slowIndex]=nums[fastIndex]; } } return slowIndex + 1;//返回长度 } }