2.三数之和

 一、题目描述

https://leetcode-cn.com/problems/3sum/

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

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

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

二、解题思路

解此题的主要想法是先对数组排序,再依此固定一个数,然后再去找另外两个数,使得三个数之和等于0。
           (1)在固定一个数后,找另外两个数的过程中要使得找数的时间尽可能的少,所以可以设置两个指针l、r分别从左右两边向中间找。
          (2)因为题目的要求是不可以包含重复的三元组,所以 i 固定数,l、r在找数的过程中要把这些重复的答案去掉。
              如:在 l<r 的情况下,如果 l 和 l+1 指向的数相等,则此时应该跳过 l 至 l+1,r 同理;
                      i 在固定数的过程中亦是如此,如果 i 指向的值等于 i-1(上一次固定的数),则应该跳过这种情况;
          (3)剪枝优化:因为数组是已经排序的,如果如果遍历到 i 指向的值大于0时,则肯定不存在 i 和后面的两个数相加等于0的情况。

代码如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

public class ThreeSum {
	public static List<List<Integer>> threeSum(int[] nums){
		if(nums == null)
			return null;
		if(nums.length<3)
			return new ArrayList<>();
		
		Arrays.parallelSort(nums); //对数组nums进行排序
		List<List<Integer>> ls = new ArrayList<>();
		
		//让i从数组下标为0开始
		for(int i=0;i<nums.length-2;i++) { //因为每次都会操作i和i后面的另外两个数,所以只遍历至倒数第3个数即可
			if(nums[i]>0)
				break; //因为数组已经有序,如果遍历到第i个元素为正的话,那么它后面的元素的值都为正,不存在和为0的情况
			
			//跳过可能重复的答案,如下标i、i-1指向的值可能相等,也就是说当前要处理数据在上一次已经处理过了。
			if(i==0 || (i>0 && nums[i] != nums[i-1])) {
				//l从i的后一个元素开始
				int l = i+1;
				//r从数组的最后一个数(最大的一个数)往前
				int r = nums.length - 1;
				
				while(l<r) {
					if(nums[i] + nums[l] + nums[r] == 0) {
						ls.add(Arrays.asList(nums[i],nums[l],nums[r]));
						while(l<r && nums[l] == nums[l+1])
							l++; //去掉重复的结果,注意l++后的l指向的是元素的值和nums[l]是相等,所以下面还需要一次l++
						while(l<r && nums[r] == nums[r-1])
							r--; //同上
						l++;
						r--;
					}else if(nums[i]+nums[l]+nums[r]<0) {
						//此时i是固定的,r指向的是数组中最大的元素(相对),所以要让三数之和去等于0,需要增大l指向的元素
						while(l<r && nums[i] == nums[l+1])
							l++; //跳过相同的情况
						l++;
					}else { //三数之和大于0,必须减小r指向的元素
						while(l<r && nums[r] == nums[r-1])
							r--;
						r--;
					}
				}
			}
		}//for
		return ls;
	}
	
	public static void main(String[] args) {
		int[] nums = new int[] {-1,0,1,2,-1,-4};
		List<List<Integer>> ls = threeSum(nums);
		
		for(List<Integer> it : ls) {
			for(int item : it) {
				System.out.print(item+" ");
			}
			System.out.println();
		}
	}
}

猜你喜欢

转载自blog.csdn.net/kz57350132/article/details/89947691