当前位置:首页 > > 程序员小灰
[导读]前段时间,我们介绍了LeetCode上面的一个经典算法题“两数之和问题”。这一次,我们把问题做一下扩展,尝试在数组中找到和为“特定值”的三个数。

前一段时间,我们介绍了LeetCode上面的一个经典算法题【两数之和问题】。


这一次,我们把问题做一下扩展,尝试在数组中找到和为“特定值”的三个数。


题目的具体要求是什么呢?给定下面这样一个整型数组:



我们随意选择一个特定值,比如13,要求找出三数之和等于13的全部组合。


由于5+6+2=13, 5+1+7=13,3+9+1=13,所以最终的输出结果如下:


【5, 6,2】

【5, 1,7】

【3, 9,1】



小灰的思路,是把原本的“三数之和问题”,转化成求n次“两数之和问题”。



我们以上面这个数组为例,选择特定值13,演示一下小灰的具体思路:


第1轮,访问数组的第1个元素5,把问题转化成从后面元素中找出和为8(13-5)的两个数:


如何找出和为8的两个数呢?按照上一次所讲的,我们可以使用哈希表高效求解:


第2轮,访问数组的第2个元素12,把问题转化成从后面元素中找出和为1(13-12)的两个数:



第3轮,访问数组的第3个元素6,把问题转化成从后面元素中找出和为7(13-6)的两个数:



以此类推,一直遍历完整个数组,相当于求解了n次两数之和问题。


    public static List> threeSum(int[] nums, int target) {
        List> resultList = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            Map map = new HashMap<>();
            int d1 = target - nums[i];
            //寻找两数之和等于d1的组合
            for (int j = i+1; j < nums.length; j++) {
                int d2 = d1 - nums[j];
                if (map.containsKey(d2)) {
                    resultList.add(Arrays.asList(nums[i], d2, nums[j]));
                }
                map.put(nums[j], j);
            }
        }
        return resultList;
    }


在上面的代码中,每一轮解决“两数之和问题”的时间复杂度是O(n),一共迭代n轮,所以该解法总的时间复杂度是O(n²)。


至于空间复杂度,同一个哈希表被反复构建,哈希表中最多有n-1个键值对,所以该解法的空间复杂度是O(n)。



我们仍然以之前的数组为例,对数组进行升序排列:




这样说起来有些抽象,我们来具体演示一下:


第1轮,访问数组的第1个元素1,把问题转化成从后面元素中找出和为12(13-1)的两个数。


如何找出和为12的两个数呢?我们设置两个指针,指针j指向剩余元素中最左侧的元素2,指针k指向最右侧的元素12:


计算两指针对应元素之和,2+12 = 14 > 12,结果偏大了。


由于数组是按照升序排列,k左侧的元素一定小于k,因此我们把指针k左移一位:


计算两指针对应元素之和,2+9 = 11< 12,这次结果又偏小了。


j右侧的元素一定大于j,因此我们把指针j右移一位:


计算两指针对应元素之和,3+9 = 12,正好符合要求!


因此我们成功找到了一组匹配的组合:1,3,9


但这并不是结束,我们要继续寻找其他组合,让指针k继续左移:

 计算两指针对应元素之和,3+7 = 10< 12,结果偏小了。


于是我们让指针j右移:


计算两指针对应元素之和,5+7 = 12,又找到符合要求的一组:


1,5,7


我们继续寻找,让指针k左移:


 计算两指针对应元素之和,5+6 = 11< 12,结果偏小了。


于是我们让指针j右移:


此时双指针重合在了一起,如果再继续移动,就有可能和之前找到的组合重复,因此我们直接结束本轮循环。


第2轮,访问数组的第2个元素2,把问题转化成从后面元素中找出和为11(13-2)的两个数。


我们仍然设置两个指针,指针j指向剩余元素中最左侧的元素3,指针k指向最右侧的元素12:


 计算两指针对应元素之和,3+12 = 15 > 11,结果偏大了。


我们让指针k左移:


 计算两指针对应元素之和,3+9 = 12 > 11,结果仍然偏大。


我们让指针k继续左移:


 计算两指针对应元素之和,3+7 = 10 < 11,结果偏小了。


我们让指针j右移:


 计算两指针对应元素之和,5+7 = 12 > 11,结果又偏大了。


我们让指针k左移:


 计算两指针对应元素之和,5+6 = 11,于是我们又找到符合要求的一组:


2,5,6


我们继续寻找,让指针k左移:


此时双指针又一次重合在一起,我们结束本轮循环。


按照这个思路,我们一直遍历完整个数组。


像这样利用两个指针指向数组两端,不断向中间靠拢调整来寻找匹配组合的方法,就是双指针法,也被称为“夹逼法”。


    public static List> threeSumv2(int[] nums, int target) {
        Arrays.sort(nums);
        List> resultList = new ArrayList>();
        //大循环
        for (int i = 0; i < nums.length; i++) {
            int d = target - nums[i];
            // j和k双指针循环定位,j在左端,k在右端
            for (int j=i+1,k=nums.length-1; j                // k指针向左移动
                while (jd) {
                    k--;
                }
                //双指针重合,跳出本次循环
                if (j == k) {
                    break;
                }
                if (nums[j] + nums[k] == d) {
                    List list = Arrays.asList(nums[i], nums[j], nums[k]);
                    resultList.add(list);
                }
            }
        }
        return resultList;
    }


上面这段代码表面上有三层循环,但每一轮指针j和k的移动次数加起来最多n-1次,因此该解法的整体时间复杂度是O(n²)。


最关键的是,该解法并没有使用额外的集合(排序是直接在输入数组上进行的),所以空间复杂度只有O(1)!


—————END—————



喜欢本文的朋友,欢迎关注公众号 程序员小灰,收看更多精彩内容

      
点个[在看],是对小灰最大的支持!


免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

逻辑分析、高效能运算核心、灵活自动化烧录、先进通讯协议

关键字: 嵌入式 自动化 RS-485 接口

覆盖 TI MCU、MPU 和无线连接解决方案的统一、生产就绪平台,消除迁移障碍,并缩短全球 Zephyr 开发者的上市时间 上海2026年10月14日 /美通社/ --...

关键字: RTOS 嵌入式 TI 开发者

在物联网终端、无线传感节点、便携采集设备与无人值守嵌入式控制系统中,电池续航是决定产品实用性与运维成本的核心指标。多数低功耗嵌入式设计过度依赖软件休眠、数字时钟裁剪等数字节能手段,却忽略了模拟电路长期静态漏电、有源器件偏...

关键字: 嵌入式 控制系统 低功耗

随着物联网设备向微型化、多频段、低成本、快迭代方向快速发展,嵌入式天线设计已成为硬件开发的核心瓶颈。传统板载天线、陶瓷天线、FPC天线方案,普遍存在设计周期长、PCB布局限制多、频段适配性差、量产一致性低等问题,极大拖慢...

关键字: 天线 物联网 嵌入式

随着汽车向电动化、智能化、网联化高速迭代,车载嵌入式系统的功能复杂度、控制精度与可靠性要求大幅提升。传统车用嵌入式系统多采用“纯数字MCU+外置模拟芯片”的分立架构,存在线路繁琐、信号损耗大、响应延迟高、故障率偏高等问题...

关键字: 嵌入式 汽车电子 模拟芯片

随着生活节奏不断加快,一次采购更多食材、提前规划家庭饮食,逐渐成为不少消费者的日常习惯。尤其对于追求高品质生活的家庭而言,冰箱不仅需要拥有充足的储存空间,更需要在长时间储存过程中尽可能保持食材原有的口感与状态。然而,传统...

关键字: 十字门冰箱 净化系统 嵌入式

触觉行业论坛(HIF)制定的规范为可编程触觉提供了通用框架;Vector Haptics API控制、实时音频转触觉及双通道驱动,则为产品团队提供了紧凑的集成路径

关键字: 可编程触觉 处理器 嵌入式

我一直对谷歌助手在我们说“好,谷歌”或“嘿,Siri”时立即开始录音的机制感到着迷。这种启发促使我探索如何将唤醒词检测技术应用于嵌入式设备。在这个项目中,我也意识到在树莓派等小型板载计算机(SBC)上运行时需要进行必要的...

关键字: 嵌入式 树莓派 计算机 INMP441

在万物互联的数字化浪潮中,物联网技术打破了传统设备的信息孤岛,而嵌入式视觉作为设备感知物理世界的核心载体,正依托物联网架构完成颠覆性变革。不同于传统机器视觉依赖云端处理、固定场景作业的局限,物联网驱动下的嵌入式视觉,实现...

关键字: 物联网 嵌入式 视觉
关闭