首页 > 代码库 > 18. 4Sum
18. 4Sum
一、描述
1、题目
2、题意
给一个数组,和一个目标数,求满足数组中的4个数的和为目标数的所有组合!
二、解答
1、思路:
数组排序后,依次从前向后取一个数 num[i], target - num[i] 即为下标 i 后面 三数之和。再依次遍历 i 后的数,将目标数记为 target - num[i] - num[j],化为两数之和。最终采用2变量分别指向 j 后一个数与数组最后一个数,相对遍历,查出满足的所有情况!
public List<List<Integer>> fourSum(int[] nums, int target) { Arrays.sort(nums); List<List<Integer>> resultList = new ArrayList<List<Integer>>(); List<Integer> targetList = null; int tempTarget = 0, maxLen = nums.length - 1; for(int i = 0; i <= maxLen; i++) { if(i == 0 || nums[i] != nums[i-1]) for(int j = i + 1; j <= maxLen; j++) { tempTarget = (target - nums[i] - nums[j]); int low = j+1; int high = maxLen; while(low < high) { if(nums[low] + nums[high] == tempTarget) { targetList = Arrays.asList(nums[i], nums[j], nums[low], nums[high]); resultList.add(targetList); low++; high--; } else if(nums[low] + nums[high] < tempTarget) low++; else high--; } } } List newList = new ArrayList(new HashSet(resultList)); return newList; }
2、改进
查看到大神回答,可以过滤更多的不符合情况,来增加遍历的速度!测试的速度提高了一半多!
public class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { List<List<Integer>> res = new ArrayList<List<Integer>>(); int len = nums.length; if(nums == null || len < 4) return res; Arrays.sort(nums); int max = nums[len-1]; if(4*nums[0] > target || 4*max < target) return res; int z; for(int i = 0; i < len; i++) { z = nums[i]; if(i > 0 && z == nums[i-1]) continue; if(z + 3*max < target) continue; if(4*z > target) break; if(4*z == target) { if(i + 3 < len && nums[i+3] == z) res.add(Arrays.asList(z, z, z, z)); break; } threeSumForFourSum(nums, target - z, i+1, len - 1, res, z); } return res; } private void threeSumForFourSum(int[] nums, int target, int low, int high, List<List<Integer>> fourSumList, int z) { if(low + 1 >= high) return; int max = nums[high]; if(3 * nums[low] > target || 3 * max < target) return; int z1; for(int i = low; i < high - 1; i++) { z1 = nums[i]; if( i > low && z1 == nums[i-1]) continue; if(z1 + 2*max < target) continue; if(3*z1 > target) break; if(3 * z1 == target) { if(i + 1 < high && nums[i+2] == z1) fourSumList.add(Arrays.asList(z1, z1, z1, z)); break; } twoSumForFourSum(nums, target - z1, i + 1, high, fourSumList, z1, z); } } private void twoSumForFourSum(int[] nums, int target, int low, int high, List<List<Integer>> fourSumList, int z1, int z2) { if(low >= high) return; if(2 * nums[low] > target || 2 * nums[high] < target) return; int i = low, j = high, sum, x; while(i < j) { sum = nums[i] + nums[j]; if(sum == target) { fourSumList.add(Arrays.asList(z1, z2, nums[i], nums[j])); x = nums[i]; while(++i < j && x == nums[i]) ; x = nums[j]; while(i < --j && x == nums[j]) ; } if(sum < target) ++i; if(sum > target) j--; } } }
三、总结
在遍历嵌套层次较多的情况下,用 if 判断过滤不符条件,可以明显提高运行速度!
18. 4Sum
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。