algorithm-base/animation-simulation/求和问题/四数之和.md

152 lines
5.9 KiB
Java
Raw Normal View History

2021-07-23 15:44:19 +00:00
> 如果阅读时发现错误或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
2021-03-20 08:44:27 +00:00
>
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
>
2021-07-23 15:44:19 +00:00
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入。
2021-03-20 08:44:27 +00:00
#### [18. 四数之和](https://leetcode-cn.com/problems/4sum/)
2021-03-19 07:26:58 +00:00
## 题目描述
> 给定一个包含 n 个整数的数组 nums 和一个目标值 target判断 nums 中是否存在四个元素 abc d 使得 a + b + c + d 的值与 target 相等找出所有满足条件且不重复的四元组
>
> 注意
>
> 答案中不可以包含重复的四元组
示例
> 给定数组 nums = [1, 0, -1, 0, -2, 2] target = 0
>
> 满足要求的四元组集合为
> [
2021-07-23 15:44:19 +00:00
> [-1, 0, 0, 1],
2021-03-19 07:26:58 +00:00
> [-2, -1, 1, 2],
2021-07-23 15:44:19 +00:00
> [-2, 0, 0, 2]
2021-03-19 07:26:58 +00:00
> ]
我们已经完成了两数之和和三数之和这个题目应该就手到擒来了因为我们已经知道这类题目的解题框架两数之和呢我们就先固定第一个数 然后移动指针去找第二个符合的三数之和固定一个数双指针去找符合情况的其他两位数那么我们四数之和也可以先固定两个数然后利用双指针去找另外两位数所以我们来搞定他吧
### 多指针
#### 解析
三数之和是我们首先确定一个数然后利用双指针去找另外的两个数我们在这个题目里面的解题思路是需要首先确定两个数然后利用双指针去找另外两个数和三数之和思路基本一致很容易理解我们具体思路可以参考下图
这里需要注意的是我们的 target 不再和三数之和一样为 0 target 是不固定的所以解题思路不可以完全照搬上面的题目另外这里也需要考虑去重的情况思路和上题一致
![四数之和起始](https://cdn.jsdelivr.net/gh/tan45du/tan45du.github.io.photo@master/photo/四数之和起始.2mi8qclt1h40.png)
上图则为我们查找到一个符合条件的四元组的情况查找成功之后下一步移动蓝色指针重新定义绿蓝指针继续执行上面步骤
![四数之和例子](https://cdn.jsdelivr.net/gh/tan45du/tan45du.github.io.photo@master/photo/四数之和例子.3xy3mil2rp40.png)
动图解析
![四数之和](https://cdn.jsdelivr.net/gh/tan45du/tan45du.github.io.photo@master/photo/四数之和.337d5ffc7040.gif)
#### 题目代码
```java
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
if(nums.length < 4){
2021-07-23 15:44:19 +00:00
return new ArrayList<>();
2021-03-19 07:26:58 +00:00
}
Arrays.sort(nums);
List<List<Integer>> arr = new ArrayList<>();
for (int i = 0; i < nums.length-3; ++i) {
if (i > 0 && nums[i] == nums[i-1]) {
continue;
}
for (int j = i+1; j < nums.length-2; j++) {
if (j > i+1 && nums[j] == nums[j-1]) {
continue;
}
int l = j+1;
int r = nums.length-1;
while (l < r) {
int sum = nums[i] + nums[j] + nums[l] + nums[r];
if (sum == target) {
//存入
arr.add(new ArrayList<>
(Arrays.asList(nums[i], nums[j], nums[l], nums[r])));
//去重
while (l < r && nums[l] == nums[l+1]) {
l++;
}
while (l < r && nums[r] == nums[r-1]) {
r--;
}
l++;
r--;
}
else if (sum > target) {
r--;
}
else {
l++;
}
}
}
}
return arr;
}
}
```
2021-07-27 18:26:32 +00:00
Go Code:
```go
func fourSum(nums []int, target int) [][]int {
res := [][]int{}
length := len(nums)
if length < 4 {
return res
}
sort.Ints(nums)
for i := 0; i < length - 3; i++ {
// 去重
if i != 0 && nums[i] == nums[i - 1] {
continue
}
for j := i + 1; j < length - 2; j++ {
// 去重
if j != i + 1 && nums[j] == nums[j - 1] {
continue
}
l, r := j + 1, length - 1
for l < r {
/*
// 下面两个for循环的去重也可以用下面的代码替换
if l != i + 1 && nums[l] == nums[l - 1] {
l++
continue
}
*/
sum := nums[i] + nums[j] + nums[l] + nums[r]
if sum == target {
res = append(res, []int{nums[i], nums[j], nums[l], nums[r]})
for l < r && nums[l] == nums[l + 1] {
l++
}
for l < r && nums[r] == nums[r - 1] {
r--
}
l++
r--
} else if sum < target {
l++
} else {
r--
}
}
}
}
return res
}
```