LeetCode_3Sum

32 篇文章 0 订阅

3Sum

Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
  • The solution set must not contain duplicate triplets.

    For example, given array S = {-1 0 1 2 -1 -4},

    A solution set is:
    (-1, 0, 1)
    (-1, -1, 2)
之前Leetcode出过两个数相加的题目,这次是三个数,要求找出一个乱序数组中满足要求的三个数,要求这三个数之和为0,可能有若干个三元组,注意每个三元组不能重复,且每个三元组内的三个数字为非降序排列的。
解题思路:分析一下三元组的特点,有以下两种情况:1、三个数全为零;2、一定有一个正数,一个负数,还有一个可为正数可为负数可为零。所以,首先把该数组进行升序排列,排列后分为三种情况讨论:1、第一个数字为零;2、最后一个数字为零;3、第一个数字小于零且最后一个数字大于零。除了以上三种情况的其他情况均无解,下面来分析以上三种情况:
第一种情况:第一个数字为零,判断第二、三个数字是否也为零,是则有解且唯一:[[0,0,0]]。
第二种情况:最后一个数字为零,判断倒数第二、倒数第三个数字是否也为零,是则有解且唯一:[[0,0,0]]。
第三种情况:最常见的情况,头小于零,尾大于零。由于一定有一个正数、一个负数,所以设置两个指针i和j指向头和尾,零减去这两个数之和得到第三个数,判断第三个正负性,若是非负数且比j指向的正数小,则开始从j-1向左搜索,直到负数出现;若第三个数是负数且比i指向的负数大,则开始从i+1向右搜索,直到非负数出现。如此循环,再将j自减1,重新循环,直到j指向的数变为非正数,此时将i自加1,再将j重新指向最后一个数字,重新循环遍历。
java代码实现:
public static List<List<Integer>> threeSum(int[] nums) {
		
		Arrays.sort(nums);
		System.out.println(Arrays.toString(nums));
		
		List<List<Integer>> fi = new ArrayList<List<Integer>>();
		int i=0,j=nums.length-1;
		if(nums.length>2){
		if(nums[i]==0)
			if(nums[1]==0&&nums[2]==0){
				List<Integer> sig = new ArrayList<Integer>();
				sig.add(0);
				sig.add(0);
				sig.add(0);
				fi.add(sig);
				System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2));
				return fi;
			}
		if(nums[j]==0)
			if(nums[j-1]==0&&nums[j-2]==0){
				List<Integer> sig = new ArrayList<Integer>();
				sig.add(0);
				sig.add(0);
				sig.add(0);
				fi.add(sig);
				System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2));
				return fi;
			}
		int temp_i=nums[i];
		int temp_j=nums[j];

		while(nums[i]<0&&nums[j]>0){
			while(nums[j]>0){
				int res = -(nums[i]+nums[j]);
				if(res>=0&&res<=nums[j]){
					for(int key=j-1;nums[key]>=0;key--){
						if(nums[key]==res){
							List<Integer> sig = new ArrayList<Integer>();
							sig.add(nums[i]);
							sig.add(res);
							sig.add(nums[j]);
							fi.add(sig);
							System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2));
					//		sig.clear();
							break;
						}
					}
				}
				else if(res<0&&res>=nums[i]){
					for(int key=i+1;nums[key]<0;key++){
						if(nums[key]==res){
							List<Integer> sig = new ArrayList<Integer>();
							sig.add(nums[i]);
							sig.add(res);
							sig.add(nums[j]);
							fi.add(sig);
							System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2));
						//	sig.clear();
							break;
						}
					}
				}
				temp_j=nums[j];
				j--;
				while(nums[j]>0&&nums[j]==temp_j)
					j--;
			}
			j=nums.length-1;
			temp_i=nums[i];
			i++;
			while(nums[i]<0&&nums[i]==temp_i)
				i++;
		}
		if(nums[i]==0&&i+2<=nums.length-1)
			if(nums[i+1]==0&&nums[i+2]==0){
				List<Integer> sig = new ArrayList<Integer>();
				sig.add(0);
				sig.add(0);
				sig.add(0);
				fi.add(sig);
				System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2));
			}
		}
		return fi;
		
	}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值