二分查找
二分查找
1.使用条件:有序数组且互不重复
2.前闭后闭:
-
left=0;right=nums.length-1;//右端需要保证闭区间必须减一
- 因为右端点有定义,所以判断条件while (left <= right) 要使用 <=
- if (nums[middle] > target) right 要赋值为 middle - 1
class Solution {
public int search(int[] nums, int target) {
//二分查找左闭右闭
int left=0,right=nums.length-1;
while(left<=right) {
int middle=left+(right-left)>>1;
if(target<nums[middle])
right=middle-1;
else if(target>nums[middle])
left=middle+1;
else if (target==nums[middle])
return middle;
}
return -1;
}
}
3.前闭后开
-
left=0;right=nums.length;
- while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
- if (nums[middle] > target) right 更新为 middle
class Solution { public int search2(int[] nums, int target) { //二分查找左闭右开 int left = 0, right = nums.length; while (left < right) { // 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; } return -1; } }
移除元素(双指针法)
题目链接:. - 力扣(LeetCode)
文章讲解:代码随想录
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
整个过程保持不变的性质是:区间 [0,left)[0,left})[0,left) 中的元素都不等于 val。当左右指针遍历完输入数组以后,left 的值就是输出数组的长度。
这样的算法在最坏情况下(输入数组中没有元素等于 val\textit{val}val),左右指针各遍历了数组一次。
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
// 时间复杂度:O(n) // 空间复杂度:O(1) class Solution { public: int removeElement(vector<int>& nums, int val) { int slowIndex = 0; for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) { if (val != nums[fastIndex]) { nums[slowIndex++] = nums[fastIndex]; } } return slowIndex; } };
- 相向双指针方法
基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
如果左指针 left 指向的元素等于 val,此时将右指针 right 指向的元素复制到左指针 left 的位置,然后右指针 right 左移一位。如果赋值过来的元素恰好也等于 val,可以继续把右指针 right指向的元素的值赋值过来(左指针 left指向的等于 val 的元素的位置继续被覆盖),直到左指针指向的元素的值不等于 val 为止。
当左指针 left和右指针 right重合的时候,左右指针遍历完数组中所有的元素。
这样的方法两个指针在最坏的情况下合起来只遍历了数组一次。与方法一不同的是,方法二避免了需要保留的元素的重复赋值操作。
public int removeElement4(int[] nums, int val) {
int left = 0;
int right = nums.length;
while (left < right) {
if (nums[left] == val) {
nums[left] = nums[right - 1];
right--;
} else {
left++;
}
}
return left;
}
小技巧:
1.left + ((right -left) >> 1) == (left + right) /2
left + right 在某种情况下可能会超过基本类型所能容纳的最大值,而且 >> (位运算) 比 / 运算要快一点
2.数组的输出的方式
调用Array.toString(a),返回一个包含数组元素的字符串,这些元素被放置在括号内,并用逗号分开
System.out.println(Arrays.toString(array));