【LeetCode热题100】--15.三数之和

2023-09-18 11:06:51

15.三数之和

image-20230918103833462

注意:最后答案中不能包含重复的三元组

使用排序+双指针

可以使用三重循环枚举三元组,但是需要哈希表进行去重操作,得到不包含重复三元组的最终答案,消耗量大量的时间和空间

对于不重复的本质,保持三重循环的大框架不变,只需要保证:

  • 第二重循环枚举到的元素不小于当前第一重循环枚举到的元素
  • 第三重循环枚举到的元素不小于当前第二重循环枚举到的元素

也就是说,我们枚举到的三元组(a,b,c)满足a≤b≤c,保证了只有(a,b,c)这个顺序会被枚举到,而(b,a,c)和(c,b,a)这些不会,这样就减少了重复,要实现这一点,可以将数组中的元素从小到大进行排序

同时,保证在每一重循环中,相邻两次枚举的元素不相同,避免重复

此时,时间复杂度仍未 O ( N 3 ) O(N^3) O(N3),仍然没有跳出三重循环的大框架,因此继续优化,进一步,如果我们固定了前两重循环枚举到的元素a和b,那么只有唯一的c满足a+b+c=0,当第二重循环往后枚举一个元素b’时,由于b’>b,那么满足a+b’+c’=0的c’一定有c’<c,即c‘在数组中一定出现在c的左侧,也就是说,我们可以从小到大枚举b,同时从大到小枚举c,即第二重循环和第三重循环实际上是并列的关系,这就是双指针:当我们需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法,将枚举的时间复杂度从 O ( N 2 ) O(N^2) O(N2)减少至 O ( N ) O(N) O(N)

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);  //先对数组进行排序
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        //枚举a
        for(int first = 0;first < n; first++){
            //需要和上一次枚举的数不相同,只有和上一次枚举的元素不相同时,才会进行枚举
            if(first > 0 && nums[first] == nums[first - 1]){
                continue;
            }
            // c对应的指针指向数组的最右端
            int third = n - 1;
            int target = -nums[first];
            // 枚举b
            for(int second = first + 1;second<n;second++){
                //同样需要和上一次枚举的元素不相同
                if(second > first + 1 && nums[second] == nums[second -1]){
                    continue;
                }
                //保证b的指针在c的指针的左侧
                while(second < third && nums[second] + nums[third] > target){
                    --third;
                }
                //如果指针重合,随着b后续的增加
                // 就不会有满足a+b+c=0并且b<c了,可以退出循环
                if(second == third){
                    break;
                }
                if(nums[second] + nums[third] == target){
                    List<Integer> list = new ArrayList<Integer>();
                    list.add(nums[first]);
                    list.add(nums[second]);
                    list.add(nums[third]);
                    ans.add(list);
                }
            }

        }
        return ans;
    }

}
更多推荐

Redis GEO 类型与 API 结合,地理位置优化的绝佳实践

🔭嗨,您好👋我是vnjohn,在互联网企业担任Java开发,CSDN优质创作者📖推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代🌲文章所在专栏:MySQL、Redis、业务设计🤔我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识💬向我询问任何您想要的东西

JavaWeb 学习笔记 3:Servlet

JavaWeb学习笔记3:Servlet1.简介Servlet是JavaEE定义的一套Web应用开发标准(接口),实现了该技术的Web服务器软件(如Tomcat)上可以运行一个Servlet容器,只要我们使用Servlet技术开发Web应用,就可以打成war包后放在Web服务器上,Web服务器软件可以自动解包,并执行其

vSAN数据恢复-vSAN架构下虚拟机磁盘组件出现问题的数据恢复案例

vsan数据恢复环境:一套VMwarevSAN超融合基础架构,全闪存,开启压缩重删。共11台服务器节点。每台服务器节点上配置1块PCIE固态硬盘和8-10块SSD固态硬盘。每个服务器节点上创建1个磁盘组,每个磁盘组将1个PCIE固态硬盘识别为2个硬盘作为缓存盘,将8-10个SSD固态硬盘作为容量盘,共同组成vSAN存储

AMEYA360 | 罗姆ROHM面向工业设备应用的产品目录上线

作为半导体和电子元器件制造商,罗姆集团自成立后60多年以来,一直秉持“质量第一”的企业目的,为消费电子设备和IT设备、汽车以及工业设备等多个领域源源不断地提供高品质、可信赖的产品。随着“节能”和“小型化”需求的不断高涨,罗姆集团以功率半导体和模拟半导体为中心,正面向“工厂自动化”、“能源”和“基础设施”等工业设备市场,

建议收藏《Verilog代码规范笔记_华为》(附下载)

华为verilog编程规范是坊间流传出来华为内部的资料,其贴合实际工作需要,是非常宝贵的资料,希望大家善存。至于其介绍,在此不再赘述,大家可看下图详细了解,感兴趣的可私信领取《Verilog代码规范笔记_华为》。…………一共10页想获得完整版《Verilog代码规范笔记_华为》的小伙伴赶快私信获取!另外,今天精选了几道

ITIL是什么?

ITIL是什么?1.ITIL是什么?2.ITIL4个版本2.1ITILV1-关注IT基础架构的管理2.2ITILV2-以流程为核心(5个服务支持流程和5个服务交付流程)2.3ITILV3-服务生命周期2.4ITIL4-最新版本,强调价值创造2.5ITILV1,V2,V3到ITIL4时间线3.ITIL4有哪些内容?3.1

ISTQB术语表

此术语表为国际软件测试认证委员会(ISTQB)发布的标准术语表。此表历经数次修改、完善,集纳了计算机行业界、商业界及政府相关机构的见解及意见,在国际化的层面上达到了罕有的统一性及一致性。参与编制此表的国际团体包括澳大利亚、比利时、芬兰、德国、印度、以色列、荷兰、挪威、葡萄牙、瑞典、英国和美国。多数软件测试工程师使用19

四川玖璨电子商务有限公司专注抖音电商运营

四川玖璨电商是一个靠谱的抖音培训公司,在电商行业内有着广泛的知名度和良好的口碑。该公司通过多年的发展,形成了独特的运营理念和有效的运营策略,为商家提供了一站式的抖音电商运营服务。首先,四川玖璨电子商务有限公司注重与商家的沟通和合作。公司专门设立了客户服务团队,与商家建立紧密的合作关系。商家可以随时与团队成员进行沟通,了

vue点击pdf文件直接在浏览器中预览文件

好久没有更新文章了,说说为什么会有这篇文章呢,其实是应某个热线评论的要求出的,不过由于最近很长一段时间没打开csdn现在才看到,所以才会导致到现在才出。先来看看封装完这个预览方法的使用,主打一个方便使用:id:为文件idname:为文件名称ajaxDownLoadFile(id,name)没错就是这么简单,调用这个函数

采棉机工作过程的关键动作

1、起动:确认机械变速手柄和液压手柄在空挡位置——确认手油门在最小位置——关闭所有照明开关和电气——打开钥匙开关——检查所有仪表是否符合起动的要求——灯检——响喇叭警示周围人员——起动(800—900转/分稳定后)——怠速(1200转/分)运行2分钟(冬天4分钟)。2、熄火:停车(一般不要使用制动器,防止采棉机前倾栽头

TypeScript项目配置

前言我们需要建立tsconfig.json作用用于标识TypeScript项目的根路径;用于配置TypeScript编译器;用于指定编译的文件。重要字段files-设置要编译的文件的名称;include-设置需要进行编译的文件,支持路径模式匹配;exclude-设置无需进行编译的文件,支持路径模式匹配;compiler

热文推荐