双指针(二)
- 题目特征:数组、数据有序
移动零
快慢指针也是双指针,但是两个指针从同一侧开始遍历数组,将这两个指针分别定义为
快指针(fast)
和慢指针(slow)
,两个指针以不同的策略移动,直到两个指针的值相等(或其他特殊条件)为止,如fast每次增长两个,slow每次增长一个。
快慢指针做法:
慢指针:指向0
快指针:指向非0
当两个指针符合要求,交换元素
每次循环维护指针,快指针永远在慢指针前面
class Solution {
public void moveZeroes(int[] nums) {
int low = 0;//指向0元素
int fast = 1;//指向非0元素
while(fast < nums.length && low < nums.length) {
if(nums[low] == 0 && nums[fast] != 0) {
int t = nums[low];
nums[low] = nums[fast];
nums[fast] = t;
}
if(nums[fast] == 0) {
fast++;
}
if(nums[low] != 0) {
low++;
if(fast <= low) {
fast = low + 1;
}
}
}
}
}
非双指针做法:
class Solution { public void moveZeroes(int[] nums) { int sum=0; for(int i=0;i<nums.length;i++){ if(nums[i]==0){ sum++; } else if(sum!=0){ nums[i-sum]=nums[i]; nums[i]=0; } } } }
这个想法很有趣,利用特性
两数之和 II - 输入有序数组
碰撞指针,一左一右
如果numbers[right] + numbers[left],右边界减1;否者左边界加1;
如果相等,则直接的返回。
class Solution {
public int[] twoSum(int[] numbers, int target) {
int[] rs = new int[2];
int left = 0;
int right = numbers.length -1;
while(right > left) {
int temp = numbers[right] + numbers[left];
if(temp > target) {//结果大于目标值,右指针减小,最大值减小
right--;
} else if(temp < target) {//结果小于目标值,左指针增大,最大值增加
left++;
} else {
rs[1] = right + 1;
rs[0] = left + 1;
return rs;
}
}
return rs;
}
}