leetcode18 四数之和(递归版)

115 阅读1分钟
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四
元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
 
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

提示:
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109

我们希望的是使用一种解决方式然后满足三个及以上的元素相加等于target, 最容易想到的就是递归的方式。对二个数的求值我们可以使用map的方式存储循环过的元素。

对于上题我们的实现方式

1、排序: 排序的作用是我们能避免相同的元素进行重复使用,造成结果的重复。

2、递归: 递归的作用是当我们需要计算的元素较多的时候,我们首先处理三数之和,其余的数字会存储在temp中,用最后三个数来找target结果的变化

var fourSum = function(nums, target) {
    nums.sort((a, b) => a - b)
    let result=[];
    let len=nums.length;
    const func = (index, n, temp) => {
        if (n < 3) {
            return
        }

        for(let i=index; i<len; i++) {
            if(i > index && nums[i] === nums[i-1]) { // 如果当前元素和之前的元素相等直接跳过
                continue
            }

            if (n>3) {
                func(i+1, n-1, [nums[i], ...temp]); // 把后三个数之外的元素存在temp中
                continue;
            }

            let start=i+1;
            let end=len-1;

            while(start<end) {
                let sum = nums[i] + nums[start] + nums[end] + temp.reduce((prev, curr) => prev + curr)

                if(sum === target) {
                    result.push([...temp, nums[i], nums[start++], nums[end--]]);

                    while(nums[start] === nums[start-1]) {
                        start++
                    }
                    while(nums[end] === nums[end+1]) {
                        end++
                    }

                } else if (sum > target) {
                    end--
                } else {
                    start++
                }

            }
        }
    }
    func(0, 4, [])
    return result
};