LeetCode 18. 4Sum

一 题目

Given an array nums of n integers and an integer target, are there elements abc, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

The solution set must not contain duplicate quadruplets.

Example:

Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.

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

二 分析

 题目是数组4个元素和为指定target。难度是medium级别。

前面做过类似的题目。可以先看看,2sum.入门系列Two Sum   时间复杂度是O(n) 线性的。

 leetcode 15. 3Sum  ,暴力循环是O(n^3), 使用降维的方式,先排序+滑动窗口,可以做到O(n^2).

同理,对于4sum也可以套用这种方式。时间复杂度O(n^3).比3sum多了一层循环。

public static void main(String[] args) {
		int[] nums ={1, 0, -1, 0, -2, 2};
		List<List<Integer>> res = fourSum(nums,0);
		System.out.println(JSON.toJSON( res) );
	}
	
	 public static List<List<Integer>> fourSum(int[] nums, int target) {		 
		 
		 List<List<Integer>> reslist = new ArrayList<List<Integer>>();
		 if (nums.length < 4) return reslist;
		 //先排序
		 Arrays.sort(nums);
		 for(int i=0;i<= nums.length-4;i++){
			 
			 for(int j=i+1;j<= nums.length-3;j++){
				 
				 int left = j+1;
			     int right = nums.length-1;
			
			     while(left< right){
			         int sum = nums[i]+nums[j]+nums[left]+nums[right];
					 if(sum==target){						
						 List<Integer> tlist = Arrays.asList(nums[i],nums[j],nums[left],nums[right]);				
						 if(!reslist.contains(tlist)){
						 reslist.add(tlist);
						 }
						 right --;
					 }
					 else if(sum>target){
						 right --;
				     }else {
				    	 left++;
				     }
			     }
			 }
			 
		 } 
		 
		return reslist;	        
	 }

Runtime: 27 ms, faster than 42.64% of Java online submissions for 4Sum.

Memory Usage: 38 MB, less than 100.00% of Java online submissions for4Sum.

看提交结果,应该有更好的方案。目前已经从O(n^4)降到了O(n^3).

如何更快呢?

hashmap存储两两之和

public static List<List<Integer>> fourSum(int[] nums, int target) {
		
		 List<List<Integer>> reslist = new ArrayList<List<Integer>>();
		 if (nums.length < 4) return reslist;
		 //先排序
		 Arrays.sort(nums);
		 
		 //两两求和
		 Map<Integer,List<Integer[]>> map = new HashMap();
		 for(int i=0;i<nums.length-1;i++ ){
			 for(int j=i+1;j< nums.length;j++ ){
				 Integer[] pair = {i, j};			
				 int tmp = nums[i]+nums[j];
				 if(!map.containsKey(tmp)){
					 map.put(tmp, new ArrayList<Integer[]>());
				 }
				 map.get(tmp).add(pair);				 
			 }
		 }		
		 
		 //rule
		 for (int i = 0; i < nums.length-1; i ++)
	        {
	            for (int j = i + 1; j < nums.length; j ++)
	            {
	            	int gap = target - nums[i] - nums[j];
	            	if(!map.containsKey(gap)){//不包含
	            		continue;
	            	}
	            	List<Integer[]> list = map.get(gap);
	            	for(int k=0;k< list.size(); k++){
	            		//有重合
	            		if(i<= list.get(k)[1]){
	            			continue;
	            		}
	            		List<Integer> tlist = new ArrayList<>();
	            		tlist.add(nums[i]);
	            		tlist.add(nums[j]);
	            		tlist.add(nums[list.get(k)[0]]);
	            		tlist.add(nums[list.get(k)[1]]);
	            		if(!reslist.containsAll(tlist)){
	            		reslist.add(tlist);
	            		}
	            	}          
	            }
	        }    		 
		 
		 return reslist;
		
	}

 我试着提交下,

Runtime: 34 ms, faster than 24.38% of Java online submissions for 4Sum.

Memory Usage: 39 MB, less than 84.06% of Java online submissions for4Sum.

真的不快,应该是我的代码写的有问题,没有达到网上说的那种  平均O(n^2),最坏O(n^4)。

有空在研究下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值