[LeetCode][15]3Sum解析与快速排序算法-Java实现
Posted 胖子程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode][15]3Sum解析与快速排序算法-Java实现相关的知识,希望对你有一定的参考价值。
Q:
Given an array S of n integers,
are there elements a, b, c 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实现的主要内容,如果未能解决你的问题,请参考以下文章