对撞指针

# 对撞指针

对撞指针是双指针中的一种常见类型,一个指针从头部开始,而另一个指针从尾部开始。典型的应用场景是从两端向中间迭代数组。一般来说,利用对撞指针的前提是数组有序。经典题型有:反转字符串、验证回文串、两数之和等。

# 对撞指针图示

对撞指针

# 经典题型

话不多说,直接上经典题型,因为也没太多好说的。

# LC 344. 反转字符串 (opens new window)

Q:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

A:典型的对撞指针解法。

/**
 * @param {character[]} s
 * @return {void} Do not return anything, modify s in-place instead.
 */
var reverseString = function (s) {
    let left = 0;
    let right = s.length - 1;
    while (left < right) {
        const tmp = s[left];
        s[left] = s[right];
        s[right] = tmp;

        left++;
        right--;
    }
};

# LC 125. 验证回文串 (opens new window)

Q:给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

A:双指针,对撞指针

/**
 * @param {string} s
 * @return {boolean}
 */
var isPalindrome = function (s) {
    const isValid = (char) => {
        const isNumber = char >= "0" && char <= "9";
        const isLetter = (char >= "A" && char <= "Z") || (char >= "a" && char <= "z");
        return isNumber || isLetter;
    }

    let left = 0;
    let right = s.length - 1;
    while (left < right) {
        if (!isValid(s[left])) {
            left++;
        } else if (!isValid(s[right])) {
            right--;
        } else {
            if (s[left].toLowerCase() != s[right].toLowerCase()) return false;
            left++;
            right--;
        }
    }
    return true;
};

# LC 167.两数之和-ii-输入有序数组 (opens new window)

Q:给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

A:由于数组已有序,可用双指针,对撞指针解决。

/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function (numbers, target) {
    let left = 0;
    let right = numbers.length - 1;
    while (left < right) {
        const sum = numbers[left] + numbers[right];
        if (sum == target) return [left + 1, right + 1];
        if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    return [];
};

# LC 11. 盛最多水的容器 (opens new window)

Q:给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。

A:对撞指针的经典题目,需要仔细理解,详细题解看官方题解

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function (height) {
    let left = 0;
    let right = height.length - 1;
    let ans = 0;
    while (left < right) {
      	// 计算当前面积
        const area = (right - left) * Math.min(height[left], height[right]);
        ans = Math.max(ans, area);
      
        // 移动较小的一侧
        if (height[left] < height[right]) {
            left++;
        } else {
            right--;
        }
    }
    return ans;
};

# 附录

# 经典题目列表

Last Updated: 6/23/2022, 5:33:14 PM