哈希表 - 三数之和

15. 三数之和


方法一:排序+双指针

javascript 复制代码
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    const res = [], len = nums.length;
    // 将数组排序
    nums.sort((a, b) => a - b)
    for (let i = 0; i < len; i++) {
        let l = i + 1, r = len - 1, iNum = nums[i];
        // 将数组排过序,如果第一个数大于0直接返回res
        if (iNum > 0) return res
        // 去重
        if (iNum == nums[i - 1]) continue
        while (l < r) {
            let lNum = nums[l], rNum = nums[r], threeSum = iNum + lNum + rNum
            // 三数之和小于0,则左指针向右移动
            if (threeSum < 0) l++
            else if (threeSum > 0) r--
            else {
                res.push([iNum, lNum, rNum])
                // 去重
                while (l < r && nums[l] == nums[l + 1]) {
                    l++
                }
                while (l < r && nums[r] == nums[r - 1]) {
                    r--
                }
                l++
                r--
            }
        }
    }
    return res
};

方法二:递归

javascript 复制代码
/**
 *  nsum通用解法,支持2sum,3sum,4sum...等等
 *  时间复杂度分析:
 *  1. n = 2时,时间复杂度O(NlogN),排序所消耗的时间。、
 *  2. n > 2时,时间复杂度为O(N^n-1),即N的n-1次方,至少是2次方,此时可省略排序所消耗的时间。举例:3sum为O(n^2),4sum为O(n^3)
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function (nums) {
    // nsum通用解法核心方法
    function nSumTarget(nums, n, start, target) {
        // 前提:nums要先排序好
        let res = [];
        if (n === 2) {
            res = twoSumTarget(nums, start, target);
        } else {
            for (let i = start; i < nums.length; i++) {
                // 递归求(n - 1)sum
                let subRes = nSumTarget(
                    nums,
                    n - 1,
                    i + 1,
                    target - nums[i]
                );
                for (let j = 0; j < subRes.length; j++) {
                    res.push([nums[i], ...subRes[j]]);
                }
                // 跳过相同元素
                while (nums[i] === nums[i + 1]) i++;
            }
        }
        return res;
    }

    function twoSumTarget(nums, start, target) {
        // 前提:nums要先排序好
        let res = [];
        let len = nums.length;
        let left = start;
        let right = len - 1;
        while (left < right) {
            let sum = nums[left] + nums[right];
            if (sum < target) {
                while (nums[left] === nums[left + 1]) left++;
                left++;
            } else if (sum > target) {
                while (nums[right] === nums[right - 1]) right--;
                right--;
            } else {
                // 相等
                res.push([nums[left], nums[right]]);
                // 跳过相同元素
                while (nums[left] === nums[left + 1]) left++;
                while (nums[right] === nums[right - 1]) right--;
                left++;
                right--;
            }
        }
        return res;
    }
    nums.sort((a, b) => a - b);
    // n = 3,此时求3sum之和
    return nSumTarget(nums, 3, 0, 0);
};
相关推荐
kiracrimson7 小时前
从缓存的角度看链表与线性表的差异
数据结构·链表·缓存
心抵鹊8 小时前
归并排序之翻转对(hard)
数据结构·算法
FfHUCisI9 小时前
Golang Map 哈希表实现
golang·哈希算法·散列表
白狐_79812 小时前
408 数据结构|红黑树插入:只记两大类
数据结构
Lost of 程序猿17 小时前
.NET 线程安全集合与并发数据结构深度实战:从 lock 到无锁
数据结构·安全·.net
机器学习之心17 小时前
基于BiGRU-Attention的轴承剩余寿命预测(MATLAB实现):从振动信号到RUL曲线的完整闭环
数据结构·算法·matlab·轴承剩余寿命预测·振动信号·bigru-attention
青梅橘子皮17 小时前
优选算法---专题2(滑动窗口)
数据结构·算法
程序猫.17 小时前
双指针问题
java·数据结构·算法
50万马克的面包18 小时前
数据结构:线性表 —— 顺序表与链表完整总结
数据结构·链表
白狐_79818 小时前
408 数据结构|散列表构造题:开放定址法做题套路
数据结构·散列表