一、双指针算法的常见类型
-
同向双指针:
-
两个指针从同一侧开始移动,通常用于滑动窗口或链表操作。
-
-
对向双指针:
-
两个指针从两侧向中间移动,通常用于有序数组的搜索或判断问题。
-
-
快慢双指针:
-
两个指针以不同速度移动,通常用于链表中的环检测或中点查找。
-
二、双指针算法的应用场景
-
有序数组的两数之和。
-
滑动窗口问题。
-
链表的环检测。
-
去重或删除特定元素。
三、双指针算法的 JavaScript 示例
1. 移动零
题目:
给定一个数组
nums
,编写一个函数将所有0
移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
示例 2:
输入: nums =[0]
输出:[0]
提示:
1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1
代码:
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function(nums) {
let right = nums.length-1
for(let i = 0 ; i<right ; i++ ){
if(nums[i]==0){
nums.splice(i,1)
nums.push(0)
right--
i--
}
}
};
题解代码:
class Solution {
public void moveZeroes(int[] nums) {
int n = nums.length;
int zeroNum = 0;
for(int i = 0; i < n; i++) {
if(nums[i] == 0) {
zeroNum++;
continue;
}
if(zeroNum > 0) {
nums[i - zeroNum] = nums[i];
nums[i] = 0;
}
}
}
}
2. 三数之和
题目:
给你一个整数数组
nums
,判断是否存在三元组[nums[i], nums[j], nums[k]]
满足i != j
、i != k
且j != k
,同时还满足nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为0
且不重复的三元组。注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。示例 2:
输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。示例 3:
输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。
代码:
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
nums.sort((a,b)=>a-b)
let result = []
for(let i = 0 ; i < nums.length-2 ; i++ ){
if(nums[i]>0) break;
if(i&&nums[i]==nums[i-1])continue
let left = i+1 , right = nums.length-1
while(left<right) {
sum = nums[i]+nums[left]+nums[right]
if(sum==0){
result.push([nums[i],nums[left++],nums[right--]])
while(left<right&&nums[left]==nums[left-1]) left++
while(left<right&&nums[right]==nums[right+1]) right--
}else if(sum>0){
right--
}else{
left++
}
}
}
return result
};