一、做题链接:18. 四数之和 - 力扣(LeetCode)
二、题目分析
1.做这一道题之前本博主建议先看上一篇《三数之和》
2.题目分析
给你一个由
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:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
由题可知:做这个题要主要面临的困难是去重和漏选,去重主要利用的是排序,set等,漏选就枚举
示例解析[1,0,-1,0,-2,2]->排序后[-2,-1,0,0,1,2]
以此类推得出最终答案
三、算法分析
1.暴力枚举法:排序+四层for循环+set去重;时间复杂度O(n^4)-----》这个不可跑过力扣
2.双指针+单调性+两层for循环;时间复杂度O(n^3)-》利用率三数之和--》利用率两数之和
算法步骤:
1.排序
2.设置第一个固定数
3.设置第二个固定数
4.两数之和,设置两个指针left,right-》降低复杂度的关键
5.细节处理,重点关注去重问题
注意事项:
去重:1.去除第一固定数的重如:0,0,求出来的一样
2.去除第二个数的重如:第一固定数是-1,第二固定数:0,0结果一样
3.去除两数之和的重
四、代码编写
public List<List<Integer>> fourSum(int[] nums, int target) {Arrays.sort(nums);//排序List<List<Integer>> Foursum = new ArrayList<>();for (int i = 0; i < nums.length; )//固定一个数{for (int j = i + 1; j < nums.length;)//固定第二个数{long tar = (long) target - nums[i] - nums[j];//求出两数之和的目标List<Integer> list = new ArrayList<>();//两数之和int left = j + 1;int right = nums.length - 1;while (left < right) {if (left < nums.length && nums[left] + nums[right] < tar) {left++;} else if (right > 0 && nums[left] + nums[right] > tar) {right--;} else {list.add(nums[i]);list.add(nums[j]);list.add(nums[left]);list.add(nums[right]);Foursum.add(list);//去除第三重while (left < nums.length && nums[left] == list.get(2)) {left++;}while (right > 0 && nums[right] == list.get(3)) {right--;}}}//去除第二重j++;while (j < nums.length && nums[j] == nums[j - 1]) {j++;}}//去除第三重i++;while (i<nums.length && nums[i]==nums[i-1]){i++;}}return Foursum;}
你学废了吗