首页 > 试题广场 >

四数之和

[编程题]四数之和
  • 热度指数:1183 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个长度是 n 的数组 nums ,和一个目标值 target,请你找出不重复的四元组 [nums[a],nums[b],nums[c],nums[d]] (如果四元组的元素一一对应则只输出其中一组)
同时四元组要满足 各不相同,
你可以按任意顺序输出

数据范围:
示例1

输入

[2,0,-2,3,-3,0],0

输出

[[2,-2,0,0],[3,-3,0,0],[2,-2,3,-3]]
# -*- coding: utf-8 -*-

# coding:utf-8
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @param target int整型
# @return int整型二维数组
#
class Solution:
    """
    题目:
        https://www.nowcoder.com/practice/d5b74806fa104518903884e182f47e35?tpId=196&tqId=40414&rp=1&ru=/exam/oj&qru=/exam/oj&sourceUrl=%2Fexam%2Foj%3Fpage%3D7%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D196&difficulty=undefined&judgeStatus=undefined&tags=&title=
    算法:
        题目要求获取nums[a] + nums[b] + nums[c] + nums[d] = target的所有不同组合[nums[a], nums[b], nums[c], nums[d]]
        枚举nums[a]: # a的取值范围[a: n-3)
            对a去重
            枚举nums[b]:# b的范围[a+1: n-2)
                对b去重
                双指针c和d,在区间[b+1:n)中,寻找满足条件的组合,同时对c, d分别去重
    复杂度:
        时间复杂度:O(N^3),N为数组nums的长度
        空间复杂度:O(N),排序算法所需的空间复杂度
    """

    def fournumber(self, nums, target):
        # write code here
        n = len(nums)

        nums.sort()

        res = []
        for a in range(n - 3):
            if a > 0 and nums[a] == nums[a - 1]: # 对a去重,剪枝
                continue
            for b in range(a + 1, n - 2):
                if b > a + 1 and nums[b] == nums[b - 1]: # 对b去重,剪枝
                    continue
                c, d = b + 1, n - 1
                while c < d:
                    Sum = nums[a] + nums[b] + nums[c] + nums[d]
                    if Sum == target:
                        res.append([nums[a], nums[b], nums[c], nums[d]])
                        while c < d and nums[c] == nums[c + 1]: # 对c去重,剪枝
                            c += 1
                        while c < d and nums[d] == nums[d - 1]: # 对d去重,剪枝
                            d -= 1
                        c += 1
                        d -= 1
                    elif Sum > target:
                        d -= 1
                    else:
                        c += 1
        return res


if __name__ == "__main__":
    sol = Solution()

    # nums, target = [2, 0, -2, 3, -3, 0], 0

    # nums, target = [2, 0, -2, 0, 1, -3, 4, -4], -4

    nums, target = [3, 2, 4, -3, -5, -3, -2, 2, 0, 4, -3], 1

    res = sol.fournumber(nums, target)

    print res

发表于 2022-06-23 10:37:53 回复(0)
package main
import "sort"

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param nums int整型一维数组 
 * @param target int整型 
 * @return int整型二维数组
*/
func fournumber( nums []int ,  target int ) [][]int {
    ans:=[][]int{}
    sort.Ints(nums)
    for i:=0;i<len(nums);i++{
        if i>0&&nums[i]==nums[i-1]{
            continue
        }
        for j:=i+1;j<len(nums);j++{
            if j>i+1&&nums[j]==nums[j-1]{
                continue
            }
            l,r:=j+1,len(nums)-1
            for l<r{
                sum:=nums[i]+nums[j]+nums[l]+nums[r]
                if sum==target{
                    ans=append(ans,[]int{nums[i],nums[j],nums[l],nums[r]})
                    for l<r&&nums[l]==nums[l+1]{
                        l++
                    }
                    for l<r&&nums[r]==nums[r-1]{
                        r--
                    }
                    l++
                    r--
                }else if sum>target{
                    r--
                }else{
                    l++
                }
            }
        }
    }
    return ans
}

发表于 2023-03-29 10:36:42 回复(0)

思路和三数之和相同。

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer>> fournumber (ArrayList<Integer> nums, int target) {
        Collections.sort(nums);
        ArrayList<ArrayList<Integer>> res = new ArrayList<>(); 
        for(int one = 0; one < nums.size() - 3; ++one) {
            for(int two = one + 1; two < nums.size() - 2; ++two) {
                int left = two + 1, right = nums.size() - 1;
                while(left < right) {
                    double temp =nums.get(left) +nums.get(right) + nums.get(one) +nums.get(two);
                    if((double)target == temp) {
                        ArrayList<Integer> templist= new ArrayList<>();
                        templist.add(nums.get(one));
                        templist.add(nums.get(two));
                        templist.add(nums.get(left));
                        templist.add(nums.get(right));
                        if(!res.contains(templist))
                            res.add(templist);
                        left++;
                    } else  if(nums.get(one) +nums.get(two) +nums.get(left) +nums.get(right) < target) {
                        left++;
                    } else right--;
                }
            }
        }
        return res;
    }
}
发表于 2023-02-21 17:30:04 回复(0)
通过这道题复习了一个知识点,list.get获取的值不能用==比较,因为是包装类型所以要用equals比较
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums int整型ArrayList
     * @param target int整型
     * @return int整型ArrayList<ArrayList<>>
     */
    public  ArrayList<ArrayList<Integer>> fournumber(ArrayList<Integer> nums,
            int target) {
        // write code here
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if (nums.size() < 4) {
            return res;
        }
        Collections.sort(nums);
        int n = nums.size();
        for (int i = 0; i < n - 3; i++) {
            //对第一个数进行去重
            if (i > 0 && nums.get(i).equals(nums.get(i - 1))) {
                continue;
            }
            //直至四数之和大于target还没有找到结果,就停止遍历
            if ((long) nums.get(i) + nums.get(i + 1) + nums.get(i + 2) + nums.get(
                        i + 3) > target) {
                break;
            }
            //找到与最大的三个数的四数之和大于target的,根据这个区间寻找符合条件的组
            if ((long) nums.get(i) + nums.get(n - 1) + nums.get(n - 2) + nums.get(
                        n - 3) < target) {
                continue;
            }
            for (int j = i + 1; j < n - 2; j++) {
                //第二个数原理相同
                if (j > i + 1 && nums.get(j).equals(nums.get(j - 1))) {
                    continue;
                }
                if ((long) nums.get(i) + nums.get(j) + nums.get(j + 1) + nums.get(
                            j + 2) > target) {
                    break;
                }
                if ((long) nums.get(i) + nums.get(j) + nums.get(n - 1) + nums.get(
                            n - 2) < target) {
                    continue;
                }
                //双指针遍历存在区间
                int left = j + 1, right = n - 1;
                while (left < right) {
                    int sum = nums.get(i) + nums.get(j) + nums.get(left) + nums.get(right);
                    //双指针遍历找到满足条件的组
                    //防止所有元素相同
                    if (sum == target) {
                        ArrayList<Integer> list = new ArrayList<>();
                        list.add(nums.get(i));
                        list.add(nums.get(j));
                        list.add(nums.get(left));
                        list.add(nums.get(right));
                        res.add(list);
                        //left和right去重,同时由于left和right的值已经加入集合,需要额外移动一次指针,找到新值
                        while (left < right && nums.get(left).equals(nums.get(left + 1))) {
                            left++;
                        }
                        left++;
                        while (left < right && nums.get(right).equals(nums.get(right - 1))) {
                            right--;
                        }
                        right--;
                    } else if (sum < target) {
                        left++;
                    } else {
                        right--;
                    }
                }
            }
        }
        return res;
    }
}


发表于 2022-09-13 11:31:27 回复(0)
function fournumber( nums ,  target ) {
    // write code here
    nums.sort((a, b) => a-b);
    let res = [];
    let max = nums.length-1;
    let i = 0;
    let num1 = nums[i];
    while(i < nums.length - 3) {
        let i2 = i + 1;
        let l = i2 + 1;
        let h = max;
        while(i2 < nums.length - 2){
            let num2 = nums[i2];
            let low = nums[l];
            let high = nums[h];
            while(l < h) {
                if(num1 + num2 + low + high == target) {
                    res.push([num1, num2, low, high]);
                    while(nums[l] == low) {l++;}
                    while(nums[h] == high) {h--;}
                    low = nums[l];
                    high = nums[h];
                } else if (num1 + num2 + low + high < target) {
                    while(nums[l] == low) {l++;}
                    low = nums[l];
                } else if (num1 + num2 + low + high > target) {
                    while(nums[h] == high) {h--;}
                    high = nums[h];
                }
            }
            while(nums[i2] == num2) {i2++;}
            l = i2 + 1;
            h = max;
        }
        while(num1 == nums[i]) {i++;}
        num1 = nums[i];
    }
    return res;
}

发表于 2022-06-04 19:07:05 回复(0)
class Solution {
public:
    vector<vector<int>> fournumber(vector<int>& nums, int target) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        for (int k = 0; k < nums.size(); k++) {
            // 这种剪枝是错误的,这道题目target 是任意值
            // if (nums[k] > target) {
            //     return result;
            // }
            // 去重
            if (k > 0 && nums[k] == nums[k - 1]) {
                continue;
            }
            for (int i = k + 1; i < nums.size(); i++) {
                // 正确去重方法
                if (i > k + 1 && nums[i] == nums[i - 1]) {
                    continue;
                }
                int left = i + 1;
                int right = nums.size() - 1;
                while (right > left) {
                    // nums[k] + nums[i] + nums[left] + nums[right] > target 会溢出
                    if (nums[k] + nums[i] > target - (nums[left] + nums[right])) {
                        right--;
                        // 当前元素不合适了,可以去重
                        while (left < right && nums[right] == nums[right + 1]) right--;
                    // nums[k] + nums[i] + nums[left] + nums[right] < target 会溢出
                    } else if (nums[k] + nums[i]  < target - (nums[left] + nums[right])) {
                        left++;
                        // 不合适,去重
                        while (left < right && nums[left] == nums[left - 1]) left++;
                    } else {
                        result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
                        // 去重逻辑应该放在找到一个四元组之后
                        while (right > left && nums[right] == nums[right - 1]) right--;
                        while (right > left && nums[left] == nums[left + 1]) left++;
                        // 找到答案时,双指针同时收缩
                        right--;
                        left++;
                    }
                }
 
            }
        }
        return result;
    }
};


发表于 2022-05-11 13:26:27 回复(0)
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @param target int整型 
     * @return int整型vector<vector<>>
     */
    vector<vector<int> > fournumber(vector<int>& nums, int target) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        vector<vector<int>>res;
        for(int i=0;i<n;i++){
            if(i>0&&nums[i]==nums[i-1]){
                continue;
            }
            for(int j=i+1;j<n;j++){
                if(j>i+1&&nums[j]==nums[j-1]){
                    continue;
                }
                int k=j+1,p=n-1;
                while(k<p){
                    while(k>j+1&&k<n&&nums[k]==nums[k-1]){
                        k++;
                    }
                    if(k>=p){
                        break;
                    }
                    long sum=(long)nums[i]+nums[j]+nums[k]+nums[p];
                    if(sum==target){
                        res.push_back({nums[i],nums[j],nums[k],nums[p]});
                        k++;
                    }else if(sum>target){
                        p--;
                    }else if(sum<target){
                        k++;
                    }
                }
            }
        }
        return res;
    }
};

发表于 2022-05-10 20:56:26 回复(0)

问题信息

难度:
7条回答 1784浏览

热门推荐

通过挑战的用户

查看代码