力扣15三数之和,天佑中华!!!!!!!

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[ [-1, 0, 1], [-1, -1, 2] ]
class Solution {
    	 public  List<List<Integer>> threeSum(int[] nums) {
    	 }
    	 }

这道题目很有意思,这里提供两种方法:
首先第一种是蛮力法,也是我最先想到的,嗯
这个方法的优点是思维简单,缺点是时间复杂度高,当输入数据较多时,难以获得有效的满意度。
蛮力法的思路是三次循环计算每三个组合,然后进行计算满足的三个数,和已在表中的进行对比进行去重,依次做下去。
代码如下:

	  public static List<List<Integer>> threeSum(int[] nums) {
	  List<List<Integer>> a=new ArrayList<>();
		 int len=nums.length;
		 for(int i=0;i<len-2;i++){
			 for(int j=i+1;j<len-1;j++)
				 for(int k=j+1;k<len;k++){
					 if(nums[i]+nums[j]+nums[k]==0){
						 List<Integer> temp=new ArrayList<>();
						 temp.add(nums[i]);
						 temp.add(nums[j]);
						 temp.add(nums[k]);
						 temp.sort(null);//有序的才能进行比较
						 if(!a.contains(temp)){
							 a.add(temp);					 					 
						 }
					 }
				 }
		 }	
		  return a;      
	   }

第二种是双指针法,我看了下别人的题解,用自己的语言给大家整理下
我们为了减轻复杂度,要对数组进行排序
然后呢我们对数组进行遍历,从小到大依次为最小值,当最小值都大于0时,必三数之和大于0,所以我们某种意义上就排除了一半的时间复杂度。
接下来就是循环过程中,右指针是最大值开始,左指针为最小值的前一个开始。当右指针小于等于左指针时我们要进行下一轮循环,同时在本轮循环中,当三数和大于0时,我们将右指针向左移,也就是三数之和变小
当三数之和小于0时,我们将左指针向右移,三数之和也就变大了。
我们减轻复杂度的方法,比蛮力法少了列表去重,因为我们将数组排好序后,重复的元素通过指针就自动去重了。
代码如下:

public static List<List<Integer>> threeSum(int[] nums) {
		 List<List<Integer>> a=new ArrayList<>();
		 int len=nums.length;
		  Arrays.sort(nums);//数组排序
		 if(len<3||nums==null)
			 return a;//极限条件,数组为空或长度小于3时
		 else if(nums[0]<=0&&nums[len-1]>=0){//当最小都大于0,或是最大都小于0,也就无三数之和==0的可能性了。
			 for(int i=0;i<len;i++){//开始循环
				 if(nums[i]>0) break;//最小值大于0时跳出循环
				 if(i>0&&nums[i]==nums[i-1]){
					 continue;//去除最小值的重复元素
				 }//确定左右指针位置
				 int Left=i+1;
				 int Right=len-1;
				 while(Left<Right){
					 int sum=nums[i]+nums[Left]+nums[Right];
					 if(sum==0){
						 a.add(Arrays.asList(nums[i],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<0)
						 Left++;//和小于0左指针右移,和变大
					 else if(sum>0)
						 Right--;//和大于0 右指针左移,和变小
				 }
			 }
		 }
		 return a;      
	    }

最后宣传下我个人的微信公众号,微信搜索:可及的小屋,有志向整副业,娱乐的程序员们,欢迎您的到来。谢谢。
100G程序员资料,自取哦!!
可及的小屋

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值