Leetcode:18.四数之和

130 阅读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 你可以按 任意顺序 返回答案 。

思路:

  • 整体思路和三数之和差不多,就是多了一层循环嵌套,固定两个数,再来用双指针移动
  • 要多注意的点还是去重的问题 ,在这里多写一些判断的条件,可以更快速的进行查找
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function(nums, target) {
    //定义一个接收结果的数组
    let result = []
    //若传入的数组的个数不够4个,则无法返回满足条件的四元组。
    if (nums.length<4){
        return result
    }
    //为传入的数组进行排序,即算去重
    nums.sort((a,b)=>a-b)
    //两层循环嵌套,固定四元组的两个数字
    let length= nums.length 
    //第一层循环:
    for(let i =0;i<length-3;i++){
        //若当前数与上一个数相同,则跳过当前的数,往后遍历
        if(i>0 && nums[i]===nums[i-1]){
            continue
        }
        //若数组的前四个数字的和已经>target值了,则跳出循环
        if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target){
            break
        }
        //若数组的第一个加后三个数字的和<target值,则说明i的值要增大了
        if(nums[i]+nums[length-1]+nums[length-2]+nums[length-3]<target){
            continue
        }
    //第二层循环:
        for(let j=i+1;j<length-2;j++){
            //若当前数与上一个数相同,则跳过当前的数,往后遍历
            if(j>i+1 && nums[j]===nums[j-1]){
                continue
            }
            //若数组的前四个数字的和已经>target值了,则跳出循环
            if(nums[i]+nums[j]+nums[j+1]+nums[j+2]>target){
                break
            }
            //若数组的第一个加后三个数字的和<target值,则说明j的值要增大了
            if(nums[i]+nums[j]+nums[length-1]+nums[length-2]<target){
                continue
            }
            //需要两个不断挪动的指针,计算它们四个的和,并与target进行比较。
            let start = j+1,end = length-1
            while(start<end){
                //若四个数之和===target,则判断start,end的值是否与它们的上一个数相等,相等则跳过
                if(nums[i]+nums[j]+nums[start]+nums[end]===target){  
                    result.push([nums[i],nums[j],nums[start],nums[end]])         
                while(start<end && nums[start]===nums[start+1]){
                    start++
                }
                start++
                while(start<end && nums[end]===nums[end-1]){
                    end--
                }
                end--
                }
                
                else if(nums[i]+nums[j]+nums[start]+nums[end]<target){
                    start++
                }      
                //若四个数之和>target,则说明要减小它们的和,即要end--
                else{
                    end--
                }
            }
        }
    }
    return result
    //返回最终结果

};