双指针 - 两数之和 & 两数平方和

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双指针 - 两数之和 & 两数平方和相关的知识,希望对你有一定的参考价值。

双指针 - 两数之和 & 两数平方和

题目地址: Leetcode 题解 - 双指针

这里做第一题和第二题:

  1. 有序数组的 Two Sum

    Leetcode #167

  2. 两数平方和

    Leetcode #633

这两题的题目类型和解题思路都很像,因此就放在一起了。

有序数组的 Two Sum

题目:

给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

解题思路:

  1. 已知整数数组是 升序排列

  2. 需要找出两个数字,相加之和等于目标 target

  3. 下标 从 1 开始计数

    会特地标注下标从 1 开始是因为数组正常数组下标从 0 开始,而本题需要返回的值是以 1 做起始点

  4. 你可以假设每个输入只对应唯一的答案

    这用英文理解起来其实更容易:

    The tests are generated such that there is exactly one solution.

    也就意味着每道问题有唯一解

  5. 提示为双指针,即一个 pointer left 指向最左边,一个 pointer right 指向最右边

    在已知每道题有唯一解的情况下,当 a r r a y [ l e f t ] + a r r a y [ r i g h t ] = t a r g e t array[left] + array[right] = target array[left]+array[right]=target 时,需要返回 [left+1, right+1] 即可

    a r r a y [ l e f t ] + a r r a y [ r i g h t ] < t a r g e t array[left] + array[right] < target array[left]+array[right]<target 时,也就代表着 array[left] 的数值小了,将指针 left 向右移动一格

    a r r a y [ l e f t ] + a r r a y [ r i g h t ] > t a r g e t array[left] + array[right] > target array[left]+array[right]>target 时,也就代表着 array[right] 的数值大了,将指针 right 向左移动一格

根据解题思路解题:

/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function (numbers, target) {
  // 检查边界条件
  if (!numbers || !numbers instanceof Array) {
    throw 'numbers muse be an array';
  }
  if (numbers.length < 2) {
    throw 'the length of numbers must be greater than 2';
  }

  // 先确立双指针
  let left = 0,
    right = numbers.length - 1;
  while (left < right) {
    // 当找到了 target
    if (numbers[left] + numbers[right] === target) {
      // 记住是 以 1 做起始点
      // 数组是 0-indexed,所以返回值需要+1
      return [left + 1, right + 1];
    }
    // 左边的值小了
    else if (numbers[left] + numbers[right] < target) {
      left++;
    }
    // 右边的值大了
    else {
      right--;
    }
  }
  // 加一个返回值,这个情况下就是找不到 两数之和
  // 题目中尽管说是保证会有,不过正常开发碰到这种情况还是需要处理的
  throw 'solution not found';
};

两数平方和

题目:

给定一个非负整数 c ,你要判断是否存在两个整数 ab,使得 a 2 + b 2 = c a^2 + b^2 = c a2+b2=c

解题思路:

这题的风格其实和 有序数组的 Two Sum 很像,上一题中的数组这一题可以理解成: [ 1 , 2 , 3 , . . . , c ] [1, 2, 3, ..., \\sqrt{c}] [1,2,3,...,c ] 这样一组数组。

接着再嵌套 有序数组的 Two Sum 的解题思路即可。

本题独有的条件有一个:

  • 给定一个非负整数 c

    c 必须要是正整数

根据解题思路解题:

/**
 * @param {number} c
 * @return {boolean}
 */
var judgeSquareSum = function (c) {
  if (c <= 0) {
    throw 'value must be a positive integer';
  }
  // 刚开始用的是 1,然后发现有几个测试没过
  // 因为自己审题不清楚,题目的要求:是否存在两个整数
  // 0也是整数,只不过不是正整数
  let lo = 0,
    hi = Math.floor(Math.sqrt(c));
  // 这里也同理,是否存在两个整数,题目中也没规定两个整数是否一致
  // 下面的逻辑判断与上一题一致
  while (lo <= hi) {
    if (lo ** 2 + hi ** 2 === c) {
      return true;
    } else if (lo ** 2 + hi ** 2 < c) {
      lo++;
    } else {
      hi++;
    }
  }
  return false;
};

没能一次 AC 的反思:

  1. 审题还是要审清楚,自己刷 Leecode 的时候没人问,没办法,但是在面试的时候,像这些条件一定要问清楚

  2. 做题目的时候一定要小心,不能带有惯性思维

    这题的要求是 两数的平方和,直接做完上面两数之和再做这题就忘了平方这件事情了

以上是关于双指针 - 两数之和 & 两数平方和的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 167. 两数之和 II - 输入有序数组----双指针篇六,二分篇二

算法哈希表 ( 两数之和 )

1. 两数之和---双指针篇七

数据结构与算法双指针思想——两数之和

双指针1两数之和(easy)

双指针1两数之和(easy)