leetcode 15. 3Sum

一 题目

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

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

二 分析

  本题是medium 级别。求数组里面三数之和为0的组合。

除了暴力循环外O(n^3),有个滑动窗口的降维思路,大致思想就是先取出一个数,再求两数的sum看看是否满足?

具体实现就是先排序,在滑动。基准点为a=nums[i], b= nums[left],c = nums[right]

其中初始化 left = i+1,right= nums.length-1;

分情况判断,如果符合条件,则加入结果,right向左滑动,如果《0,则left向右滑动,如果》0则right向左滑动。也就是滑动窗口往中间滑的问题。自己写的时候,还要注意一点,重复项的问题,我只是简单的结果过滤了。

代码如下:

public static void main(String[] args) {
	    int[] nums1 = {0,0,0};
        List<List<Integer>> res1  =  threeSum(nums1);
        System.out.println(res1 );
        int[] nums = {-1, 0, 1, 2, -1, -4};
        List<List<Integer>> res  =  threeSum(nums);
        System.out.println(res );
	}

	
	 public static List<List<Integer>> threeSum(int[] nums) {
		 
		 List<List<Integer>> reslist = new ArrayList<List<Integer>>();
		 if(nums== null){
			 return null;
		 }
		 //先排序
		 Arrays.sort(nums);
		 
		 for(int i=0;i<= nums.length-3;i++){
			 
			     int left = i+1;
			     int right = nums.length-1;
			     while(left< right){
				 
				 if(nums[i]+nums[left]+nums[right]==0){
					 List<Integer> tlist = Arrays.asList(nums[i],nums[left],nums[right]);
					 if(!reslist.contains(tlist)){
					 reslist.add(tlist);
					 }
					 right --;	
				 }
				 else if(nums[i]+nums[left]+nums[right]>0){
					 right --;				 
			     }else if(nums[i]+nums[left]+nums[right]<0){
			    	 left++;
			     }				
			 }			     
		 }
		 
		return reslist;
	        
	 }

Runtime: 875 ms, faster than 5.00% of Java online submissions for 3Sum.

Memory Usage: 55.1 MB, less than 5.29% of Java online submissions for3Sum.

太慢了,这是O(n^2) 吧。怎么才能提高速度呢?

网上看了大神的文章。思路还是这个思路,但是判断重复使用了指针判断相邻元素,而不是使用结果集list的判重 。

 public List<List<Integer>> threeSum(int[] nums) {
         List<List<Integer>> reslist = new ArrayList<List<Integer>>();
		 if (nums.length < 3) return reslist;
		 //先排序
		 Arrays.sort(nums);
		 
		 for(int i=0;i<= nums.length-3;i++){
			   if (i > 0 && nums[i] == nums[i - 1]) continue;   // skip duplicates
			     int left = i+1;
			     int right = nums.length-1;
			     while(left< right){
				 
				 if(nums[i]+nums[left]+nums[right]==0){							
					
					 reslist.add(Arrays.asList(nums[i],nums[left],nums[right]));
				     while (++left < right && nums[left-1] == nums[left]) {}; // skip duplicates
				     while (--right>left && nums[right+1] == nums[right]) {}; // skip duplicates
					
				 }
				 else if(nums[i]+nums[left]+nums[right]>0){
					 right --;			
			     }else {
			    	 left++;			    	
			     }				
			 }			     
		 }
		 
		return reslist;
    }

Runtime: 30 ms, faster than 83.78% of Java online submissions for 3Sum.

Memory Usage: 48.2 MB, less than 81.62% of Java online submissions for3Sum.

看似不大的改动,却极大提升了效率。666.

更多详情,参见:https://zhuanlan.zhihu.com/p/24681450

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值