[LeetCode][15]3Sum解析与快速排序算法-Java实现

Posted 胖子程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode][15]3Sum解析与快速排序算法-Java实现相关的知识,希望对你有一定的参考价值。

Q:

Given an array S of n integers, are there elements abc in S 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.

For example, given array S = [-1, 0, 1, 2, -1, -4],

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

这道题昨天我就着手看了,但是我没有很好的思路,能想到的办法也就是分治类似于得到一个数字nums[0],然后找出她的相反数这样。然后我去查了查资料,有一个解决ksum的专题,好像说这种问题很难有好的解法,应该最好就是O(n^(k-1))的复杂度。所以按照昨天的想法这样做。

1、解决这类问题为了速度肯定是要先排序的。

2、取第x个数字x从0到n-1

3、对比剩下的nums[i+1]nums[n-1](x=i);

4、如果nums[i+1]+nums[n-1]>target,那么只能n--才可能==target

如果nums[i+1]+nums[n-1]<target,那么只能i++才可能==target

5、如果i==n或者 nums[i+1]+nums[n-1]==target推出循环,x++;

这样的话一般排序最差O(n^2)而后面的排序最差也是O(n^2)所以能够保证整体算法O(n^2)。

下面我们上代码看看:

	public static void main(String[] args){
		//System.out.println();
		int[] nums = {-5,1,-3,-1,-4,-2,4,-1,-1};
//		nums = paixu(nums,0,nums.length-1);
//		for(int i : nums){
//			System.out.println(i);
//		}
		System.out.println(method(nums));
		
	}
	public static List<List<Integer>> method(int[] nums){
		List<List<Integer>> list=  new ArrayList<List<Integer>>() ;
		if(nums.length<3)
			return list;
		nums = paixu(nums,0,nums.length-1);
		for(int i : nums){
			System.out.println(i);
		}
		//找3sum
		for(int i = 0;i<nums.length;i++){
			if(i==nums.length-1)
				return list;
			for(int j = i+1,k=(nums.length-1);j!=k;){
				if(nums[j]+nums[k]>(-nums[i])){
					k--;
				}
				else if(nums[j]+nums[k]<(-nums[i])){
					j++;
				}else if(nums[j]+nums[k]==(-nums[i])){
					List numList = new ArrayList<Integer>();
					numList.add(nums[i]);
					numList.add(nums[j]);
					numList.add(nums[k]);
					//去重
					boolean flag = true;
					for(List l:list){
						if(l.toString().equals(numList.toString())){
							flag = false;
							break;
						}
						
					}
					if(flag)
					list.add(numList);
					k--;
				}

			}
		}
		
		return list;
	}
	public static int[] paixu(int[] nums,int start,int end){
		//排序
		int key  = nums[start];
		int i = start,j=end;
		while(i<j){
			while(i<j&&nums[j]>=key){
				j--;
			}
			nums[i] = nums[j];
			while(i<j&&nums[i]<=key){
				i++;
			}
			nums[j] = nums[i];
		}
		nums[j] = key;
		//System.out.println("start:"+start+"    end"+end);
		if(start!=end){
//System.out.println("j"+j);
			if(j==start)
				paixu(nums, start+1, end);
			else if(j==end)
				paixu(nums, start, end-1);
			else{
				paixu(nums,start,j-1);
				paixu(nums,j+1,end);
			}
			
		}
		return nums;
	}

虽然想法不难,但是边界检测真的很头疼啊。

后来发现有一个长串leetcode的监测例子通不过,时间太久,然后代码改成了这样:

public static void main(String[] args){
		//System.out.println();
		int[] nums = {0,0,0};
//		nums = paixu(nums,0,nums.length-1);
//		for(int i : nums){
//			System.out.println(i);
//		}
		System.out.println(method(nums));
		
	}
	public static List<List<Integer>> method(int[] nums){
		List<List<Integer>> list=  new ArrayList<List<Integer>>() ;
		if(nums.length<3)
			return list;
		//nums = paixu(nums,0,nums.length-1);
		Arrays.sort(nums);
		for(int i : nums){
			System.out.println(i);
		}
		//找3sum
		for(int i = 0;i<nums.length-2;i++){
			for(int j = i+1,k=(nums.length-1);j<k;){
				if(nums[j]+nums[k]>(-nums[i])){
					k--;
				}
				else if(nums[j]+nums[k]<(-nums[i])){
					j++;
				}else{// if(nums[j]+nums[k]==(-nums[i]))
					List numList = new ArrayList<Integer>();
					numList.add(nums[i]);
					numList.add(nums[j]);
					numList.add(nums[k]);
					System.out.println("j:"+j);
					 while (j <k  && nums[i] == nums[i+1]&&i<nums.length-2) i++;  
		             while (j < k && nums[k] == nums[k-1]) k--;  
					list.add(numList);
					j++;
				}

			}
		}
		
		return list;
	}
	public static int[] paixu(int[] nums,int start,int end){
		//排序
		int key  = nums[start];
		int i = start,j=end;
		while(i<j){
			while(i<j&&nums[j]>=key){
				j--;
			}
			nums[i] = nums[j];
			while(i<j&&nums[i]<=key){
				i++;
			}
			nums[j] = nums[i];
		}
		nums[j] = key;
		//System.out.println("start:"+start+"    end"+end);
		if(start!=end){
//System.out.println("j"+j);
			if(j==start)
				paixu(nums, start+1, end);
			else if(j==end)
				paixu(nums, start, end-1);
			else{
				paixu(nums,start,j-1);
				paixu(nums,j+1,end);
			}
			
		}
		return nums;
	}
结果还是不行。。。最后去掉了method函数中的输出可以了

以上是关于[LeetCode][15]3Sum解析与快速排序算法-Java实现的主要内容,如果未能解决你的问题,请参考以下文章

[LeetCode][15]3Sum解析与快速排序算法-Java实现

LeetCode(15) - 3Sum

Leetcode 15. 3Sum(python)

LeetCode15——3Sum

LeetCode 15 3Sum

leetcode-3Sum-15