当前位置: 首页 > news >正文

Leetcode 四数之和

在这里插入图片描述

当然可以!下面是这道题(LeetCode 18: 四数之和)的思路总览模板答案,适用于笔试、面试或者写题解时的标准答题格式👇


🧩 LeetCode 18. 四数之和 —— 思路总览模板答案

✅ 题目描述简要

给定一个整数数组 nums 和一个目标值 target,找出所有不重复的四元组 [a, b, c, d],使得:

nums[a] + nums[b] + nums[c] + nums[d] == target

要求:

  • 四元组元素的下标不重复
  • 四元组值不能重复(顺序无关)

🔍 解题思路

1. 排序数组

首先将数组 nums 升序排序,便于后续使用双指针,并且方便跳过重复元素。

2. 枚举前两个数 + 双指针找后两个数
  • 固定前两个数 nums[i]nums[j]
  • 在剩余部分使用双指针 leftright,寻找符合条件的另外两个数
3. 跳过重复元素
  • 对于每一层循环(i, j)和每次指针移动(left, right),都要跳过相同的数值,确保不出现重复的四元组
4. 使用 long 防止整型溢出
  • nums[i] + nums[j] + nums[left] + nums[right] 可能超出 int 范围,因此建议用 long 存储临时和

🧠 算法复杂度

  • 时间复杂度:O(n³)
    三重循环(两层 + 双指针)枚举所有可能组合

  • 空间复杂度:O(1)
    只用了常数级额外空间(不算返回结果)


💡 关键技巧总结

  • 排序数组:便于双指针和去重操作
  • 双指针:利用有序数组快速找到两数之和
  • 去重处理:防止重复答案(i、j、left、right层层去重)
  • long 类型:规避溢出风险

java solution

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        //首先进行排序
        Arrays.sort(nums);

        int n = nums.length;
        for(int i = 0; i < n - 3; i++) { //先确定第一个数
            if(i > 0 && nums[i] == nums[i - 1]) continue; //进行去重
            //然后确定第二个数
            for(int j = i + 1; j < n - 2; j++) {
                if(j > i + 1 && nums[j] == nums[j - 1]) continue; //去重
                //此时, 前两个数都确定了,然后开始初始化双指针
                int left = j + 1, right = n - 1;
                while(left < right) {
                    //先计算四数之和
                    long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum == target) {
                        result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                        //继续去重
                        while(left < right && nums[left] == nums[left + 1]) left++;
                        while(left < right && nums[right] == nums[right - 1] ) right--;
                        //此时left和right仍然需要移动一位,因为上面的去重只是移动到连续重复的最后一个字符
                        left++;
                        right--;
                    } else if(sum < target){
                        left++;
                    } else {
                        right--;
                    }
                }
            }
        }
 
        return result;
    }
}

当然可以!我们来一步步详细剖析这段 Java 代码的 算法思想和实现细节。目标是解决 LeetCode 第 18 题 —— 四数之和(4Sum)问题:


🧠 题目核心思想

给定一个数组 nums 和一个目标值 target,我们需要找出所有 不重复的四元组 [a, b, c, d],使得:

nums[a] + nums[b] + nums[c] + nums[d] == target

算法核心步骤(排序 + 双指针)

我们用一种 类似“三数之和”(3Sum) 的方式来解决这个问题,只不过是套两层循环 + 双指针。


🧩 代码讲解

public List<List<Integer>> fourSum(int[] nums, int target) {

我们定义一个返回值为 List 的函数,返回所有不重复的四元组。


    List<List<Integer>> result = new ArrayList<>();
    Arrays.sort(nums); // 排序,方便后面双指针处理和去重

对数组进行排序是关键,排序后我们就可以利用双指针进行查找,同时能方便地跳过重复值。


    int n = nums.length;
    for (int i = 0; i < n - 3; i++) {
        if (i > 0 && nums[i] == nums[i - 1]) continue; // 去重

第一层循环,选第一个数 nums[i]。去重防止同样的开头重复出现。


        for (int j = i + 1; j < n - 2; j++) {
            if (j > i + 1 && nums[j] == nums[j - 1]) continue; // 去重

第二层循环,选第二个数 nums[j],同样做去重。


            int left = j + 1, right = n - 1;

这时候,问题变成了:在 nums[j+1] ~ nums[n-1] 中找两个数,使得四个数的和等于 target。这正是双指针的用武之地。


            while (left < right) {
                long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];

这里我们用了 long 来存储和,是为了避免大整数相加时溢出。


                if (sum == target) {
                    result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));

如果找到满足条件的四元组,加入结果集。


                    while (left < right && nums[left] == nums[left + 1]) left++; // 去重
                    while (left < right && nums[right] == nums[right - 1]) right--; // 去重

                    left++;
                    right--;

找到一个解后,我们继续往下找新的解,但要跳过相同的值(防止重复解)。


                } else if (sum < target) {
                    left++; // 和太小,左边往右移动
                } else {
                    right--; // 和太大,右边往左移动
                }

如果当前和小于目标值,我们就让左指针右移,反之则右指针左移。


最终返回结果

    return result;
}

📈 时间复杂度分析

  • 外层两层循环:O(n^2)
  • 内层双指针扫描:O(n)
  • 所以总时间复杂度是:O(n^3),比暴力穷举 O(n^4) 快了很多。

🧹 去重机制详解

  • 第1个数 i 和第2个数 j:如果跟前一个一样,就跳过
  • 第3和第4个数:用 while 跳过重复值(排序保证相同值相邻)

🛡️ 为何使用 long 来存和?

避免整型溢出!比如 Integer.MAX_VALUE + Integer.MAX_VALUE 就会出错,所以强转为 long 保险。

相关文章:

  • IEEE PDF Xpress校验出现 :字体无法嵌入问题以及pdf版本问题
  • docker中安装 python
  • Go 语言规范学习(3)
  • 5.0 WPF的基础介绍1-Grid,Stack,button
  • 同级目录下的两个文件怎么import
  • ngx_http_core_main_conf_t
  • DeepSeek-R1 模型现已在 AWS 平台上正式上线
  • SSE SseEmitter.completeWithError(e) 触发的处理逻辑
  • 使用 PowerShell 脚本 + FFmpeg 在 Windows 系统中批量计算 MP4视频 文件的总时长
  • (C语言)文本动态通讯录(动态通讯录升级版)(C语言小项目)
  • macOS 15 通过 MacPorts 安装 PHP 7 构建错误找不到符号在 dns.o 中解决方法
  • 使用 rsync 进行服务器文件同步与优化
  • STM32基础教程——输入捕获模式测量PWM频率
  • SD(Stable Diffusion)模型学习图谱
  • 视频生成的测试时Scaling时刻!清华开源Video-T1,无需重新训练让性能飙升
  • 内网YUM源搭建手册(Internal Network yum Source Construction Manual)
  • c++ primer 阅读手记 第六章
  • RCE——回调后门
  • 【ADC测试】在ADC马密度的方式测试INL和DNL
  • 蓝桥杯python编程每日刷题 day 20
  • 昆山做网站找哪家好/上海网站优化
  • 美国网站建设公司哪家好/资源网站优化排名优化
  • 网站建设步骤与时间表/2345导航网址
  • 中小企业网站建设示范平台/南宁网站运营优化平台
  • WordPress百度自动翻译/西安百度关键词优化排名
  • 荆门网站建设公司/免费html网站模板