Leetcode15:3Sum

Leetcode15:3Sum

题目描述:3Sum

简而言之,找出数组中和为0的三个数,且不能有重复。

可以使用双指针的方法降低多重循环的时间复杂度。

解题过程

最简单的方法自然是暴力循环,先确定一个再确定后两个。但是该方法复杂度太高,而且无法通过,时间超过限制。

public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> resultList=new ArrayList<List<Integer>>();
        if (nums.length<3) {
			return resultList;
		}
        for (int i = 0; i < nums.length; i++) {
			int temp=0-nums[i];
			for (int j = i+1; j < nums.length; j++) {
				for (int j2 = j+1; j2 < nums.length; j2++) {
					if (nums[j]+nums[j2]==temp) {
						List<Integer>tempList=new ArrayList<Integer>();
						tempList.add(nums[i]);
						tempList.add(nums[j]);
						tempList.add(nums[j2]);
						Collections.sort(tempList); //去重
						if (!resultList.contains(tempList)) { //去重
							resultList.add(tempList); 
						}
					}
				}
			}
		}
        
        
        return resultList;
    }

所以可以对算法进行优化:

  • 对数组进行排序
  • 固定一个数nums[i],再用左右指针指向剩下的数的两端,即当前固定数的左边一个和nums数组的最后一个,分别为nums[left]和nums[right]。
  • 如果num[i]+nums[left]+nums[right]==0,则添入到结果列表中。

一些限制:

  • 因为数组已经排好序,所以如果当前nums[i]>0,则三个数的和不可能等于0,结束循环。
  • 如果当前nums[i]==nums[i-1],说明可能会产生与之前重复的结果,应该跳过。
  • 当找到三数之和等于0时,如果nums[left]==nums[left+1],说明可能会产生与之前重复的结果,应该将左指针右移,直接移到与nums[left]不同的数。
  • 当找到三数之和等于0时,如果nums[right]==nums[right-1],说明可能会产生与之前重复的结果,应该将右指针左移,直接移到与nums[right]不同的数。
public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> resultList=new ArrayList<List<Integer>>();
        if (nums.length<3) {
			return resultList;
		}
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
        	if (nums[i]>0) {
				break;
			}
        	if (i>0&&nums[i-1]==nums[i]) {
				continue;
			}
			int left=i+1;
			int right=nums.length-1;
			while(left<right) {
				if(nums[i]+nums[left]+nums[right]==0) {
					List<Integer>tempList=new ArrayList<Integer>();
					resultList.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 (nums[i]+nums[left]+nums[right]<0) {
					left++;
				}
				else if (nums[i]+nums[left]+nums[right]>0) {
					right--;
				}
			}
		}
        return resultList;
    }

这样优化后,就可以降低时间复杂度。
如此,可以看出,当要使用多重循环时,可以考虑使用双指针的方法减少时间复杂度。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值