LeetCode 三数之和 — 改进解法

题目:给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

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

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:

[ [-1, 0, 1], [-1, -1, 2] ]

 最开始做的解法是先将整个数组排序;然后遍历前两个数(a和b)的所有情况(n^2);对于第三个数,则从剩余的数中(即从第二个数下一个位置开始到末尾)利用二分查找出是否存在数字 -(a+b)即可。 复杂度O(n^2·logn) :

  1. class Solution {
  2. public List<List<Integer>> threeSum(int[] nums) {
  3. List<List<Integer>> ans = new ArrayList<List<Integer>>();
  4. Arrays.sort(nums);
  5. Map<Integer,Integer> mi = new HashMap();
  6. for(int i=0;i<nums.length-1;i++) {
  7. if(mi.get(nums[i]) != null) continue; //记录i下标读过的数字
  8. mi.put(nums[i],1);
  9. Map<Integer,Integer> mj = new HashMap();
  10. for(int j=i+1;j<nums.length;j++) {
  11. if(mj.get(nums[j]) != null) continue; //记录j下标读过的数字
  12. mj.put(nums[j],1);
  13. int temp = -(nums[i]+nums[j]);
  14. if(bSearch(nums,j+1,nums.length-1,temp) == false) continue; //二分搜索j下标之后的区间是否有数字temp
  15. ans.add(Arrays.asList(nums[i],nums[j],temp));
  16. }
  17. }
  18. return ans;
  19. }
  20. //二分算法
  21. public boolean bSearch(int[] nums,int s,int e,int key) {
  22. int start=s,end=e,mid;
  23. while(start<=end){
  24. mid = (start+end)/2;
  25. if(key < nums[mid]) end=mid-1;
  26. else if(key > nums[mid]) start=mid+1;
  27. else if(key == nums[mid]) return true;
  28. }
  29. return false;
  30. }
  31. }

里面有两个用了哈希的地方,所以时间复杂度应该还要乘上一个常数K...(解数组相关的题感觉总有些依赖哈希的方法=_= ...)


 最近做了另一个数组区间相关的题目,受其解法的启发,打算对这道题解法进行优化。

 还是先对数组进行排序;对第一个数字(a)进行遍历,而然后在剩余的数中用前后指针的方法找出两个和为-a的数字:两个指针left和right;left初始化为数字a的下一位置,right为最后一个位置。比较nums[left]+nums[right]+a和0的大小;如果大于0则right--,小于就left++。 其中在添加结果集时需考虑去重问题,用个哈希判断是否有重复就行了,复杂度O(n^2·K) :

  1. class Solution {
  2. public List<List<Integer>> threeSum(int[] nums) {
  3. List<List<Integer>> ans = new ArrayList<List<Integer>>();
  4. Arrays.sort(nums);
  5. Map<Integer,Integer> mi = new HashMap();
  6. for(int i=0;i<nums.length-2;i++) {
  7. if(mi.get(nums[i]) != null) continue; //记录i下标读过的数字
  8. mi.put(nums[i],1);
  9. Map<Integer,Integer> mj = new HashMap();
  10. int l = i+1, r = nums.length-1, temp;
  11. while(l<r) {
  12. temp = nums[i] + nums[l] + nums[r];
  13. if(temp < 0) {
  14. l++;
  15. } else if(temp > 0) {
  16. r--;
  17. } else {
  18. if((mj.get(nums[l])) == null) {
  19. ans.add(Arrays.asList(nums[i], nums[l], nums[r]));
  20. mj.put(nums[l], 1);
  21. }
  22. l++; r--;
  23. }
  24. }
  25. }
  26. return ans;
  27. }
  28. }

LeetCode 三数之和 — 优化解法的更多相关文章

  1. [leetcode]三数之和

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

  2. [LeetCode] 3Sum Closest 最近三数之和

    Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...

  3. [LeetCode] 3Sum 三数之和

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  4. [LeetCode] 923. 3Sum With Multiplicity 三数之和的多种情况

    Given an integer array A, and an integer target, return the number of tuples i, j, k  such that i &l ...

  5. [LeetCode] 16. 3Sum Closest 最近三数之和

    Given an array nums of n integers and an integer target, find three integers in nums such that the s ...

  6. [LeetCode] 15. 3Sum 三数之和

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  7. LeetCode:两数之和、三数之和、四数之和

    LeetCode:两数之和.三数之和.四数之和 多数之和问题,利用哈希集合减少时间复杂度以及多指针收缩窗口的巧妙解法 No.1 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在 ...

  8. [LeetCode] 3Sum Smaller 三数之和较小值

    Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 < ...

  9. LeetCode(15):三数之和

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

随机推荐

  1. day16-常用模块I(time、datetime、random、os、sys、json、pickle)

    目录 time模块 datetime模块 random模块 os模块 sys模块 json模块与pickle模块 json pickle time模块 time模块一般用于不同时间格式的转换,在使用前 ...

  2. 10.5 集合ArrayList 和 io流

    1.ArrayListToFile package day10_io_fileWrite_Read.arraylist_tofile; import java.io.BufferedWriter; i ...

  3. CAD使用GetAllAppName读所有名称(网页版)

    主要用到函数说明: MxDrawEntity::GetAllAppName 得到所有扩展数据名称,详细说明如下: 参数 说明 [out, retval] IMxDrawResbuf** ppRet 返 ...

  4. PHP 加密:Password Hashing API

    PHP 5.5 之后引入 Password hashing API 用于创建和校验哈希密码,它属于内核自带,无需进行任何扩展安装和配置.它主要提供了四个函数以供使用: password_hash(): ...

  5. 前端安全 xss

    整体的 XSS 防范是非常复杂和繁琐的,不仅需要在全部需要转义的位置,对数据进行对应的转义.而且要防止多余和错误的转义,避免正常的用户输入出现乱码. 虽然很难通过技术手段完全避免 XSS,但可以总结以 ...

  6. 总结在Linux终端中进行算术运算的6种方式

    1.使用bash 使用双括号可以像C语言一样直接使用运算符进行计算. +)) a=$((*)) echo $a b=$(($a-)) echo $b d=$(($b/)) echo $d e=$(($ ...

  7. outflow Boundary Condition in FLuent

    assumption: flow is imcompressible, fully developed, $\partial \phi / \partial X =0$, where is X is ...

  8. 洛谷 1012 拼数(NOIp1998提高组)

    [题解] 我们要做的就是把这些数排序.排序的时候判断两个数是否交换的方法,就是把这两个数相接形成两个长度相同的数字,比较这两个数字的大小. #include<cstdio> #includ ...

  9. 洛谷 4172 [WC2006]水管局长

    [题解] 我们把操作倒过来做,就变成了加边而不是删边.于是用LCT维护动态加边的最小生成树就好了.同样要注意把边权变为点权. #include<cstdio> #include<al ...

  10. maven profile多环境自动切换配置,配置分离,排除文件

    痛点: 在java开发的过程中,我们经常要面对各种各样的环境,比如开发环境,测试环境,正式环境,而这些环境对项目的需求也不相同. 在此之前,我们往往需要手动去修改相对应的配置文件然后打成war,才能部 ...