LeetCode 算法:数对和

80 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 23 天,点击查看活动详情

数对和

原题地址

设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。

示例 1:

输入: nums = [5,6,5], target = 11
输出: [[5,6]]

示例 2:

输入: nums = [5,6,5,6], target = 11
输出: [[5,6],[5,6]]

提示:

  • nums.length <= 100000

思路分析

方法一

  1. 首先遍历数组,来统计每个数字出现的次数,方便后续一个数只能属于一个数对;
  2. 然后在双层遍历数组,若 nums[i] + nums[j] === target 时,将这组数对放入 res 中,然后给 map 中的 nums[i]nums[j] 对应的数据分别减一,保证条件成立;
  3. 在运行过程中,发现若有奇数个可以组成 target 的数值时,会出现多一个的情况,查代码发现是因为两个数值相同时,在做减法的时候会出现减掉的次数少一次的情况,因此将相同和不相同的分别来处理;
  4. 最后结果因为遍历次数太多,导致超出时间限制。

方法二

  1. 吸取方法一的教训后,我们可以缩减遍历次数,争取在一次循环中搞定;
  2. 循环的过程中,查看是否有满足条件的 target - num1,有的话将对应的次数减少,并且将对应的数对存入 res 中,若不存在,则将对应的 nums[i] 的次数统计到 map 中;
  3. 最后返回 res 即可。大大缩减了执行时间。

AC 代码

方法一

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var pairSums = function(nums, target) {
    const res = []
    const map = {}
    for(let i = 0; i < nums.length; i++) {
        if(map[nums[i]]) {
            map[nums[i]] += 1
        } else {
            map[nums[i]] = 1
        }
    }
    for(let i = 0; i < nums.length; i++) {
        for(let j = 0; j < nums.length, j!== i; j++) {
            if(nums[i] + nums[j] === target) {
                if(nums[i] !== nums[j] && map[nums[i]] > 0 && map[nums[j]] > 0 || (map[nums[i]] > 1 && nums[i] === nums[j])) {
                    res.push([nums[i], nums[j]])
                    map[nums[i]] -= 1
                    map[nums[j]] -= 1
                }
                
            }
        }
    }
    return res
};

结果:

  • 执行结果: 超出时间限制

方法二

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var pairSums = function(nums, target) {
    const res = []
    const map = {}
    for(let i = 0; i < nums.length; i++) {
        const num1 = nums[i]
        const num2 = target - num1;
        if (map[num2] && map[num2] > 0) {
            map[num2] = map[num2] - 1
            res.push([num2, num1]) 
        } else {
            const num = map[num1] ? map[num1] + 1 : 1
            map[num1] = num
        }
    }
    return res
};

结果:

  • 执行结果: 通过
  • 执行用时:168 ms, 在所有 JavaScript 提交中击败了80.00%的用户
  • 内存消耗:65.4 MB, 在所有 JavaScript 提交中击败了25.71%的用户
  • 通过测试用例:42 / 42

END