LeetCode 四数之和

简介: 本题目主要是更加深化的考察双指针的运用,这里是需要在一个数组中,找到四个数的和为目标值 target 的所有三元组,其实可以先枚举两个数,剩下的两个数用双指针计算最终合并起来,得到一个结果等于期望的值。举一反三如果a + b + c + d= target , 目标值 target 是一个传入的变量,解题思路也是一样的。 对于结果集合不能重复的话,我们最常用的方式就是直接通过排序的方式来做,就可以在拿这个数据的时候,直接判断拿过了没有,拿过这个数据就跳过。下面我们就一起来看看具体的题目和解题分析吧!

四数之和


题目


给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + 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 = [], target = 0 输出:[]


提示:


0 <= nums.length <= 200 -109 <= nums[i] <= 109 -109 <= target <= 109


题目分析


1. 暴力解题


时间复杂度:O(N * N *N)

空间复杂度:O(1)


直接通过四重循环来计算。


2. 优化思路


时间复杂度:O(N * N * N)

空间复杂度:O(logN)


解题关键:排序 + 双指针。


题目中要求是不能重复的, 我们可以将输入的整个数组先排序来防止重复。


选择双指针的思路是,我们四个数的和其实可以先取出2个数,然后就看作两个数的和来处理,这样就可以灵活的运用双指针的思路了。


双指针过程中的指针移动。a , b,  c, d 下标的移动过程中。


  • a 下标需要遍历数组,得到 b + c + d 的和等于 target - a,需要通过前一个来判断是否是重复,如果已经存在就跳过。


  • b 下标需要遍历数组,得到 c + d 的和等于 target - a - b,需要通过前一个来判断是否是重复,如果已经存在就跳过。


  • c, d 双指针的移动过程,首先初始化 c 的指针位置为 b 的位置 + 1; 并且通过前一个数来判断数据是否存在重复,如果已经存在就跳过。


  • d 指针的初始指针位置为 nums.length -1 。如果 c + d >  target - a - b 那么就需要把 d 指针左移,否者右移 c 指针,因为已经排序了的。


  • 如果 c + d == target - a  - b , 表示找到真确的结果,存储到返回的结果集中。


  • 如果 c 指针 == d 指针说明已经找了一圈了,就退出本次的循环,然后在回去移动 a 或 b 指针。


解题代码


public class FourSumEqTargetValTest {
    public static void main(String[] args) {
        FourSumEqTargetValTest test = new FourSumEqTargetValTest();
        List<List<Integer>> list = test.fourSum(new int[]{1,0,-1,0,-2,2}, 0);
        System.out.println(list);
    }
    public List<List<Integer>> fourSum(int[] nums, int target) {
        // 数组长度
        int len = nums.length;
        // 排序
        Arrays.sort(nums);
        List<List<Integer>> result = new ArrayList<>();
        for (int first = 0; first < len; first++) {
            // 跳过相同的值
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            int leftVal = target - nums[first];
            for (int second = first + 1; second < len; second++) {
                // 跳过相同的值
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                int fourth = len - 1;
                int lv = leftVal- nums[second];
                for (int third = second + 1; third < len; third++) {
                    // 跳过相同的值
                    if (third > second + 1 && nums[third] == nums[third - 1]) {
                        continue;
                    }
                    // 保证 c 的指针在 d 的左边
                    while (third < fourth && nums[third] + nums[fourth] > lv) {
                        --fourth;
                    }
                    // 如果指针重合,随后 b 继续增加
                    // 如果没有满足 a + b + c + d= 0 , 并且 d < c 了, 退出循环
                    if (third == fourth) {
                        break;
                    }
                    // 找到合适的解,放入结果集合
                    if (nums[third] + nums[fourth] == lv) {
                        result.add(Arrays.asList(nums[first], nums[second], nums[third], nums[fourth]));
                    }
                }
            }
        }
        return result;
    }
}


参考资料


leetcode-cn.com/problems/4s…


相关文章
|
2月前
|
算法
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
|
2月前
|
算法
LeetCode第18题四数之和
该文章介绍了 LeetCode 第 18 题四数之和的解法,与三数之和类似,通过先排序,再用双指针确定坐标并去重的方式解决,关键是确定四个坐标,前两个通过两层循环确定,后两个通过首尾双指针确定,同时总结了双指针可减少循环次数,使解决方式更简单高效。
LeetCode第18题四数之和
|
2月前
|
算法
LeetCode第59题螺旋矩阵 II
LeetCode第59题"螺旋矩阵 II"的解题方法,通过模拟螺旋填充过程,一圈一圈从外到内按顺序填充数字,直到完成整个矩阵的构建。
LeetCode第59题螺旋矩阵 II
|
2月前
|
存储 算法
LeetCode第54题螺旋矩阵
LeetCode第54题"螺旋矩阵"的解题方法,通过模拟从外到内的螺旋遍历过程,并利用方向向量控制遍历方向的转换,有效输出矩阵的螺旋顺序。
LeetCode第54题螺旋矩阵
|
5月前
[leetcode] 四数之和 M
[leetcode] 四数之和 M
|
5月前
|
Java 测试技术 C++
leetcode-18:四数之和
leetcode-18:四数之和
40 0
|
5月前
|
Java
leetcode-53:最大子序和
leetcode-53:最大子序和
35 0
|
算法 安全 Swift
LeetCode - #54 螺旋矩阵
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
LeetCode - #54 螺旋矩阵
|
算法 安全 Swift
LeetCode - #59 螺旋矩阵 II
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
LeetCode - #59 螺旋矩阵 II
|
算法 安全 Swift
LeetCode - #18 四数之和
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。