剑指 Offer 57. 和为s的两个数字

114 阅读1分钟

题目

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

 

示例 1:

输入: nums = [2,7,11,15], target = 9
输出: [2,7] 或者 [7,2]

示例 2:

输入: nums = [10,26,30,31,47,60], target = 40
输出: [10,30] 或者 [30,10]

 

限制:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^6

解析

由于题目的数组nums是递增有序的,因此本题可以采用双指针的方法。

声明left指针指向数组头部, right指针指向数组的尾部:

  1. 如果 nums[left] + nums[right] === target, 说明找到和为target的一对,返回[ nums[left], nums[right]]即可
  2. 如果 nums[left] + nums[right] > target, 说明要缩小右边界,所以right--,
  3. 如果 nums[left] + nums[right] < target, 说明要扩大左边界,所以left++,
  4. left < right 时循环执行,反之,终止循环

nums = [2,7,11,15], target = 9 为例, 指向步骤如下:

  1. left = 0, right = 3, nums[left] = 2, nums[right] = 15, sum = 17, 和大于target, 所以选择 15 之前的数字, right--
  2. left = 0, right = 2, nums[left] = 2, nums[right] = 11, sum = 13, 和大于target, 所以选择 11 之前的数字, right--
  3. left = 0, right = 1, nums[left] = 2, nums[right] = 7, sum = 9, 和等于target, 找到题目要求的一对,返回[ nums[left], nums[right]]

参考代码

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

原题链接

剑指 Offer 57. 和为s的两个数字