Q18.四数之和
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):
- $0 <= a, b, c, d < n$
- $a、b、c 和 d 互不相同$
- $nums[a] + nums[b] + nums[c] + nums[d] == target$
你可以按 任意顺序 返回答案 。
示例 1:
1 2
| 输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
|
示例 2:
1 2
| 输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
|
提示:
- $1 <= nums.length <= 200$
- $-109 <= nums[i] <= 109$
- $-109 <= target <= 109$
思路
- 可以发现n数之和,可以递归转化为求数组中的n-1数之和
- 递归最终就是求解两数之和,可以通过排序数组左右指针的方式求出所有解法
- 注意,需要排除重复的解法,对于从左向右的求解过程中,只要元素值相同就不需要重复计算可以跳过。
- 由于target在计算过程中不断变化,为了防止溢出可以将target设置为long
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| public List<List<Integer>> fourSum(int[] nums, int target) { Arrays.sort(nums); return nSum(nums,0,target,4); } public List<List<Integer>> nSum(int[] nums, int start, long target,int n) { if(n<2 || start>=nums.length){ return new ArrayList<List<Integer>>(); } if(n==2){ return twoSum(nums,start,target); } List<List<Integer>> solutions = new ArrayList<>(); for (int i = start; i < nums.length-n+1; i++) { if(i>start && nums[i] == nums[i-1]){ continue; } int item = nums[i]; List<List<Integer>> match = nSum(nums,i+1,target-item,n-1); match.forEach(x->{ List<Integer> solution= new ArrayList<>(); solution.add(item); solution.addAll(x); solutions.add(solution); }); } return solutions; } public List<List<Integer>> twoSum(int[] nums, int start, long target) { List<List<Integer>> solutions = new ArrayList<>(); int left= start; int right = nums.length-1; while(left<right){ if(nums[left] + nums[right]> target){ right--; }else if(nums[left] + nums[right]< target) { left++; }else{ if (nums[left] + nums[right] == target) { List<Integer> solution = new ArrayList<>(); solution.add(nums[left]); solution.add(nums[right]); solutions.add(solution); while (left<right && nums[left] == nums[left+1] ){ left++; } while (left<right && nums[right] == nums[right-1]){ right--; } left ++; } } } return solutions; }
|