双指针专题
双指针法:
广泛使用在数组 链表 字符串 等移除,交换场景
- 同向双指针
- 相向双指针
本篇主要是双指针在数组中的用法
同向双指针
定义快慢两个指针
- 快指针:遍历整个集合,进行一些规则匹配
- 慢指针:代表当前符合条件的集合
对数组操作:题目关键词 原地,不使用额外空间
27. 移除元素
定义快慢两个指针,快指针遍历整个数组的元素
-
如果 不等于 val 的元素,交换 fast 和slow 对应的下标,并且慢指针移动一位;
-
如果相等,继续查看下一个。
最后结果返回慢指针的下标即可
public int removeElement(int[] nums, int val) {
int slow = 0 ;
for(int fast =0;fast<nums.length;fast++ ){
if(nums[fast]!=val){
int temp = nums[fast];
nums[fast] = nums[slow];
nums[slow] = temp;
slow++;
}
}
return slow;
}
26. 删除有序数组中的重复项
这个题比较对象是 nums[slow] 和 nums[fast].
fast 遍历整个数组,slow指示整个
-
相同 fast ++;
-
不相同,num[++slow] = num[fast]
代码
public int removeDuplicates(int[] nums) {
if(nums == null || nums.length ==0){
return 0;
}
int slow = 0;
for(int fast = 0;fast<nums.length;fast++){
if(nums[fast]!=nums[slow]){
slow++;
nums[slow] = nums[fast];
}
}
return slow+1;
}
283. 移动零
本题思路类似:27. 移除元素
fast寻找下一个不等于 零的数
相等:fast++;
不相等:交换 fast 和slow 对应的下标,并且slow 后移
public void moveZeroes(int[] nums) {
if( nums==null || nums.length == 0|| nums.length==1){
return ;
}
int slow =0;
for(int fast = 0;fast<nums.length;fast++){
if(nums[fast]!=0){
int temp = nums[fast];
nums[fast] = nums[slow];
nums[slow] = temp;
slow++;
}
}
}
相向双指针
双指针 一般是一个在开头,一个在结尾,两者相向处理问题
977. 有序数组的平方
可以先全部求平方,然后再重新升序排列即可
但是可以借助 负数平方之后不一定比正数平方之后小 使用左右指针,开始判断
-
如果 nums[left]的平方 < nums[right] 的平方 ,将 right对应的平方放到结果数组中,right 减一
-
如果 nums[left]的平方 >= nums[right] 的平方 ,将 left 对应的平方放到结果数组中,left +1
public int[] sortedSquares(int[] nums) {
if(nums.length == 0 || nums==null){
return new int[0];
}
int size = nums.length;
int left = 0;
int right = size-1;
int[] res = new int[size];
int index = size-1;
while(left<=right){
int leftVal= nums[left] * nums[left];
int rightVal = nums[right] * nums[right];
if(leftVal >=rightVal ){
res[index--] = leftVal;
left++;
}else{
res[index--] = rightVal;
right--;
}
}
return res;
}
941. 有效的山脉数组
分别从左右两边进行判断,直到不满足条件为止
最后比较看left和right
-
left==right
-
left !=0;
-
right != nums.length -1
上面三点都满足说明是山脉。如果left或者right都在起始位置,说明不是山峰
注意这里还是有一些细节,例如如下两点:
- 因为left和right是数组下标,移动的过程中注意不要数组越界
- 如果left或者right没有移动,说明是一个单调递增或者递减的数组,依然不是山峰
public static boolean validMountainArray(int[] arr) {
//特殊值判断
if(arr.length<3){
return false;
}
int size = arr.length;
int left = 0;
int right = size-1;
// 注意防止越界
while(left+1 < size && arr[left]<arr[left+1]){
left++;
}
// 注意防止越界
while(right-1 > 0 && arr[right-1 ] > arr[right]){
right--;
}
// 如果left或者right都在起始位置,说明不是山峰
if(right==left && left!=0 && right!=size-1){
return true;
}
return false;
}
重构字符串法
使用StringBuilder动态的拼接字符串
如果是字符就拼接上
如果是 # 就删除掉最后一个,但是要小心 # 太多导致删除的时候越界
双指针法
逆序操作
}
[844. 比较含退格的字符串](https://leetcode.cn/problems/backspace-string-compare/)
**重构字符串法**
使用StringBuilder动态的拼接字符串
如果是字符就拼接上
如果是 # 就删除掉最后一个,但是要小心 # 太多导致删除的时候越界
**双指针法**
逆序操作