2019-03-06-算法-进化(三数之和)

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

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

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

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

我的初步思路:利用穷举法加优化来完成,代码如下:

public List<List<Integer>> threeSum(int[] nums) {
		List<List<Integer>> list = new ArrayList<List<Integer>>();
		if(nums == null || nums.length<3) {
			return list;
		}
		//1.排序
		Arrays.sort(nums);
		Set<String> set = new HashSet<String>();
		StringBuilder sb = new StringBuilder();
        //2.查找匹配项并去重
		for(int i=0;i<nums.length-2 && nums[i]<=0;i++) {
			for(int j=i+1;j<nums.length-1;j++) {
				for(int k=j+1;k<nums.length;k++) {
					sb.delete(0, sb.length());
					if(nums[i] + nums[j] + nums[k] == 0) {
						String tmp = sb.append(nums[i]).append(nums[j]).append(nums[k]).toString();
						if(!set.contains(tmp)) {
							set.add(tmp);
							list.add(Arrays.asList(nums[i], nums[j], nums[k]));
						}
					}
				}
			}
		}
		return list;
    }

但是在测试用例输入了一个巨长巨长的数组之后,程序执行时间超出了限制。继续在穷举法上做优化的空间已经不大了。所以考虑使用另一种方法。
改用双指针法,时间勉强达标,代码如下:

public List<List<Integer>> threeSum(int[] nums) {
		List<List<Integer>> list = new ArrayList<List<Integer>>();
		if(nums == null || nums.length<3) {
			return list;
		}
		//1.排序
		Arrays.sort(nums);
		Set<String> set = new HashSet<String>();
		StringBuilder sb = new StringBuilder();
        //2.查找匹配项并去重
		for(int i=0;i<nums.length-2 && nums[i]<=0;i++) {
			int start =i+1, end = nums.length-1;
			while(nums[i]<=0 && start<end) {
				if(nums[i] + nums[start] + nums[end] <0) {
					start++;
				}else if (nums[i] + nums[start] + nums[end] >0) {
					end--;
				}else {
					sb.delete(0, sb.length());
					String tmp = sb.append(nums[i]).append(":").append(nums[start]).append(":").append(nums[end]).toString();
					if(!set.contains(tmp)) {
						set.add(tmp);
						list.add(Arrays.asList(nums[i], nums[start], nums[end]));
					}
					end--;
				}
			}
		}
		return list;
    }

上面的代码在去重方面明显还有优化空间,翻评论区发现别人的代码,参照优化如下:

public List<List<Integer>> threeSum(int[] nums) {
		List<List<Integer>> list = new ArrayList<List<Integer>>();
		if(nums == null || nums.length<3) {
			return list;
		}
		//1.排序
		Arrays.sort(nums);
        //2.查找匹配项并去重
		for(int i=0;i<nums.length-2 && nums[i]<=0;i++) {
			while (i>0 && i<nums.length-2 && nums[i] == nums[i-1])i++;
			int l =i+1, r = nums.length-1, sum=0-nums[i];
			while(nums[i]<=0 && l<r) {
				if(nums[l] + nums[r] < sum) {
					while ((l<r) && nums[l+1] == nums[l])l++;
					l++;
				}else if (nums[l] + nums[r] >sum) {
					while ((l<r) && nums[r-1] == nums[r])r--;
					r--;
				}else {
					list.add(Arrays.asList(nums[i], nums[l], nums[r]));
					while ((l<r) && nums[l+1] == nums[l])l++;
					while ((l<r) && nums[r-1] == nums[r])r--;
					r--;
				}
			}
		}
		return list;
    }

猜你喜欢

转载自blog.csdn.net/zhaohong_bo/article/details/88224664
今日推荐