什么是双指针?

双指针顾名思义就是两个指针,是一个算法思想。但双指针往往是值某几种类型的双指针,而不是仅仅就指两个指针。一般在遍历对象的过程中,使用两个相同方向(快慢指针)或者相反的方向(左右指针)的指针进行遍历。快慢指针和左右端点指针一般是解决双指针一类题的解决方法。
以下对左右指针常见问题的套路总结

左右指针的常见算法和套路

左右端点指针也称碰撞指针,最左侧的索引定义为左指针(left),最右侧的定义为右指针(right),两个指针分别从两头开始向中间进行数组遍历,互相碰面后遍历结束。

图解:

套用公式:

1
2
3
4
5
6
7
8
9
10
11
const fn = (list:number[]) => {
let left = 0;
let right = list.length - 1;
// 遍历数组
while(left <= right) {
left++;
// 一些条件判断和处理
... ...
right++;
}
}

这一般常用来解决的问题:

主要是解决数组或者是字符串中的问题。(例如:移除数组元素,翻转字符串数组,二分查找)

例子:

例1:双指针翻转字符串

1
2
3
4
5
6
7
8
9
10
11
12
const reverseString = (s: string[]): void => {
let left = 0;
let right = s.length - 1;
while (left <= right) {
if (s[left] !== s[right]) {
[s[left], s[right]] = [s[right], s[left]];
}
left++;
right--;
}
console.log('s:', s);
};

例2: 移除数组元素 给定一个数组 一个val 原地移除数组里等于val的值 返回移除后数组的长度(双指针思想)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const removeElement = (nums: number[], val: number): number => {
let left = 0;
let last = nums.length - 1;
while (left <= last) {
if (nums[left] === val) {
nums[left] = nums[last];
nums.splice(last, 1);
last--;
} else {
left++;
}
}
console.log(nums);
return left;
};

例3:两个有序数组的合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const merge2 = (nums1: number[], nums2: number[], m: number, n: number): void => {
let p = m + n - 1; // p初始值指向 nums1长度为m+n后的数组 最后一位
let p1 = m - 1; // p1指向nums1原数组的最后一位
let p2 = n - 1; // p2指向nums2数组的最后一位
// 空数组判断: 如果p1 或p2其中有一个<0 则 有一个是空数组 则直接就把nums2插入到nums1就可以了
if (p1 < 0 || p2 < 0) {
nums1.splice(0, n, ...nums2);
}
// p2 指针越界后循环结束
while (p2 >= 0) {
// 将nums1[p1]和nums2[p2]的值相比较
// 大的一方 赋值给nums1[p] p每一次循环都往前移动,p1和p2指针根据谁指的值大 谁往前移一位
if (nums2[p2] < nums1[p1]) {
nums1[p] = nums1[p1];
p--;
p1--;
} else {
nums1[p] = nums2[p2];
p--;
p2--;
}
}
console.log('merge2——nums1:', nums1);
};

例4:二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const binarySearch = (nums: number[], target: number): number => {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
const mid = left + (right - left);
if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid - 1;
} else return mid;
}
return -1;
};
binarySearch([-1, 0, 3, 5, 9, 12], 9) //输出4
binarySearch([-1, 0, 3, 5, 9, 12], 1) //输出-1

双指针之左右指针题的gitHub地址:

https://github.com/Sugar-MM/AlgorithmPractice/tree/main/src/doublePointer