双指针算法:
双指针算法一般分为3种情况:
1.普通双指针: 两个指针往同一个方向移动;
2.对撞双指针;两个指针往不同的方向移动;
3.快慢双指针.慢指针+快指针.
普通双指针:
在这里让我们举一个例子:(力扣第1题)
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
!!!注意(1.只会存在一个有效答案 2.两个数不能相同)
public int[] twoSum(int[] nums, int target) {
int a[]=new int [2];
for(int i=0;i<nums.length;i++){//定义第一个指针
for(int j=i+1;j<nums.length;j++){//定义第二个指针
if(nums[i]+nums[j]==target){
a[0]=i;
a[1]=j;
return a;
}
}
}
return new int[0];
}
对撞双指针:
让我们给一个来一个题:
给定一个整数数组 nums (该数组是有序的)和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
!!!注意(1.只会存在一个有效答案 2.两个数不能相同,3.该数组是有序的)
这里我们可以看到这个问题的条件比上一个问题给的条件多了一个该数组是有序的,这时我们就可以用到对撞双指针了.
具体该怎么样实现呢?让我们来看看代码.
public static int[] twoSum(int[] nums, int target) {
int a[] = new int[2];
int i = 0;
int j = nums.length - 1;
while (i < j) {
if (nums[i] + nums[j] > target) j--;
else if (nums[i] + nums[j] < target) i++;
else if (nums[i] + nums[j] == target) {
a[0] = i;
a[1] = j;
return a;
}
}
return new int[0];
}
这个是不是很像二分查找,但是它们之间还是有区别的,大家不要混淆了.
快慢双指针:
让我们看看力扣的第26题 删除有序数组中的重复项:
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
让我们来看看代码:
public int removeDuplicates(int[] nums) {
int ans = 0;//定义一个慢指针
for (int i = 0; i < nums.length; i ++ )//定义一个快指针,
{
if (i == 0 || nums[i] != nums[i - 1]){
nums[ans] = nums[i];
ans =ans+1;//当符合条件时,慢指针加1,不然慢指针不变
}
}
return ans;
}