问题描述

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例 2:

输入:nums = []
输出:[]

示例 3:

输入:nums = [0]
输出:[]

提示:

0 <= nums.length <= 3000
-105 <= nums[i] <= 105

解题思路(排序+双指针)

如果使用三重循环来枚举每种情况,则时间复杂度为O(N3)。
另外题中还要求答案中不可以包含重复的三元组。虽然可以使用哈希表来进行去重操作,但是这样又大大消耗了空间,而且操作起来相当的不方便,我们可以想到先将数组排好序,这样相同的元素就可以保持相邻。另外,在我们枚举的三元组 (a, b, c)满足 a≤b≤c,保证了只有 (a,b,c) 这个顺序会被枚举到,而(b,a,c)、(c,b,a) 等等这些不会,这样就减少了重复。要实现这一点,我们可以将数组中的元素从小到大进行排序,随后使用普通的三重循环就可以满足上面的要求。

Arrays.sort(nums);
for(int i=0;i<len;i++){for(int j=i+1;j<len;j++){for(int k=j+1;k<len;k++){if(nums[i]+nums[j]+nums[k]==0){//add结果集...}}}
}

对于每一重循环而言,相邻两次枚举的元素不能相同,否则也会造成重复。
而对于三重循环,我们可以固定一个指针a,然后从a的后面两端来枚举b和c,即从小到大枚举b,从大到小枚举c。这样就可以保持第二重循环不变,第三重循环变成一个从数组最右端开始向左移动的指针
当我们需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法,将枚举的时间复杂度从 O(N^2) 减少至 O(N)。为什么是 O(N)呢?这是因为在枚举的过程每一步中,「左指针」会向右移动一个位置(也就是题目中的 bb),而「右指针」会向左移动若干个位置,这个与数组的元素有关,但我们知道它一共会移动的位置数为 O(N),均摊下来,每次也向左移动一个位置,因此时间复杂度为 O(N)。

实现代码:

class Solution {private List<List<Integer>> lists;public List<List<Integer>> threeSum(int[] nums) {lists=new ArrayList<List<Integer>>();//如果数组长度小于3,无法满足有三个数,直接返回空集if(nums.length<3){return lists;} Arrays.sort(nums);int len=nums.length;for(int i=0;i<len-2;i++){//如果最左边的数都大于0,那么后面的数肯定无法满足3数之和为0,直接退出循环if(nums[i]>0){break;}//避免重复if(i!=0 && nums[i]==nums[i-1]){continue;}//定义双指针int j=i+1;int k=len-1;int prej=-1;        //prej为了去除j指针所指的元素的重复情况while(j<k){         //当j==k时退出循环//如果三数之和大于0,那么k--if((nums[j]+nums[k]+nums[i])>0){k--;//如果三数之和小于0,那么j++}else if((nums[j]+nums[k]+nums[i])<0){j++;//如果三数之和等于0}else if((nums[j]+nums[k]+nums[i])==0){//当该数在之前已经被枚举到了,仅移动指针if(prej!=-1 && nums[j]==nums[prej]){k--;j++;continue;}else{//如果没有,就添加到集合中,并标记这一次成功枚举时的指针j的位置List<Integer> list=new ArrayList<Integer>();list.add(nums[i]);list.add(nums[j]);list.add(nums[k]);lists.add(list);prej=j;}k--;j++;}}}return lists;}
}

leetcode题解15-三数之和(双指针经典)相关推荐

  1. leetcode系列--15.三数之和

    leetcode 第15题 三数之和 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三 ...

  2. Leetcode 15.三数之和 双指针 or 暴力哈希

    题目链接:传送门 题目:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组. 暴力+ ...

  3. Leetcode:NO.15 三数之和 夹逼

    题解 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复 ...

  4. leetcode No.15-16 三数之和相关问题

    leetcode 15. 三数之和 题目 链接:https://leetcode-cn.com/problems/3sum 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 ...

  5. [双指针|模拟] leetcode 15 三数之和

    [双指针|模拟] leetcode 15 三数之和 1.题目 题目链接 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ? ...

  6. LeetCode 15. 三数之和【双指针】

    15. 三数之和 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j.i != k 且 j != k ,同时还满足 nums[ ...

  7. 代码随想录算法训练营第07天 | LeetCode 454.四数相加2,383. 赎金信,15. 三数之和,18. 四数之和,总结

    LeetCode [454. 四数相加 II] 题目:给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足 ...

  8. LeetCode 15三数之和16最接近的三数之和

    三数之和(双指针) 题意: 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组. 注意 ...

  9. Leetcode python《热题 HOT 100》15. 三数之和

    Leetcode python 之 <热题 HOT 100>:https://leetcode-cn.com/problemset/hot-100/ 15. 三数之和 给定一个包含 n 个 ...

  10. LeetCode 15. 三数之和(3Sum)

    15. 三数之和 15. 3Sum 题目描述 Given an array nums of n integers, are there elements a, b, c in nums such th ...

最新文章

  1. 阿里云携手晞司盖工业,赋能设备制造商制造+服务转型升级
  2. 2020 前端开源领域技术展望
  3. 第9条:覆盖equals时总要覆盖hashCode
  4. java中四种默认的权限修饰符,Java中四种访问权限资料整理
  5. Java继承-子类不可以继承父类的构造方法
  6. 120分的转录组试题,你能得多少
  7. dmg镜像 os vm 安装mac_dmg制作笔记:个性化自己的Mac软件安装包
  8. 数据结构中的头结点和头指针
  9. GitHub 和GitLab的开发工具使用
  10. miniusbpcb封装_USB接口封装及定义大全,不用去翻手册了
  11. Excel如何实现数据排列组合
  12. winhex常用快捷键
  13. 王者荣耀服务器维护什么时间结束,3月26日全服不停机更新公告
  14. 红米3 android 版本升级失败,疑似官方推送错误固件 红米Note3全网通升级后变砖...
  15. DWC PCIE学习笔记(一)-----PCIE PHY接口
  16. 牡丹的冬季修剪及管理方法
  17. [附源码]JAVA+ssm计算机毕业设计高校请假管理系统(程序+Lw)
  18. 强化学习-入门教程(完整版)
  19. 接口自动化测试项目实战
  20. History(查看历史命令)的用法

热门文章

  1. 韩国造智能手机时代走向终结:昔日巨头纷纷关闭生产线或削减产量
  2. webpack打包教程
  3. php socket_create卡顿,phpsocket_createundefined的异常解决方法
  4. 队列阻塞_Java并发|阻塞队列ArrayBlockingQueue解析
  5. rest php,restAPI
  6. antdesignpro 重定向到登录页面_URL重定向跳转绕过
  7. fullcalendar next 不变化_让不懂编程的人爱上iPhone开发(2017秋iOS11+Swift4+Xcode9版)-第3篇...
  8. r语言调用python_python3调用R语言干货
  9. java 获取内存地址_Java 的多态在 JVM 里原来是这样的
  10. 【kafka】控制台默认不能发送大数据 4096 4095 4129