代码随想录:第7天 15. 三数之和 18. 四数之和

37 阅读2分钟

三数之和

思路:

我们对数组进行从小到大的排列

然后使用双指针 num[i] + num[left] + num[right] = target

剪枝操作: 元素都是大于0的, 当第一个元素如果大于target那么就直接结束

题目要求:不能出现重复的数组 我们需要对每个位置的元素进行去重(i left right)

当对i进行去重时,应该使用 num[i] === num[i-1] 不能使用num[i] === num[i+1],因为left在i的右边,我们需要的是每个位置的元素不同,而不是结果的数组里不能有重复

对left去重 使用 num[left] === num[left+1] left++

对right去重 num[right] === num[right-1] right --;

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
        // 因为是3个数,所以不是left <= right
        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
};

四数之和

思路和上面一样,有一个区别就是 会有负值的情况,所以不能直接和上面一样的剪枝操作,应该在大于0的情况才能剪枝 num[k]>0 && target>0 && num[k] > target

var fourSum = function(nums, target) {
    const len = nums.length;
    if(len < 4) return [];
    nums.sort((a, b) => a - b);
    const res = [];
    for(let i = 0; i < len - 3; i++) {
    
        if (nums[i] > target && nums[i] >= 0) {
            	break; // 这里使用break,统一通过最后的return返回(第一层剪枝)
            }
        // 去重nums[i]
        if(i > 0 && nums[i] === nums[i - 1]) continue;
        for(let j = i + 1; j < len - 2; j++) {
            // 第二次剪枝
            if(num[i] + nums[j] > target && nums[k] + nums[i] >= 0{
                break;
            }
            // 去重nums[j]
            if(j > i + 1 && nums[j] === nums[j - 1]) continue;
            let l = j + 1, r = len - 1;
            while(l < r) {
                const sum = nums[i] + nums[j] + nums[l] + nums[r];
                if(sum < target) { l++; continue}
                if(sum > target) { r--; continue}
                res.push([nums[i], nums[j], nums[l], nums[r]]);
		
		// 对nums[left]和nums[right]去重
                while(l < r && nums[l] === nums[++l]);
                while(l < r && nums[r] === nums[--r]);
            }
        } 
    }
    return res;
};