题目描述:
给定一个包含 n 个整数的数组 nums
和一个目标值 target
,判断 nums
中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target
相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
这道题和三数之和,两数之和特别想,有多种思路,for循环,map查找表,对撞指针等。
这道题我倾向于用对撞指针的让法,和上一篇博客,三数之和特别像,只是多了一个循环。
具体思路就是:a+b+c+d=target。a+b+c=target-d.a+b=target-c-d。然后用对撞指针,定义一个首指针,和一个尾指针,然后比较移动指针,保存数据即可,重点还是去重,详细请看上篇博客。三数之和博客:https://blog.csdn.net/weixin_37850160/article/details/88746720
代码如下:
int [] a = new int[]{5,5,3,5,1,-5,1,-2};
int target = 4;
// 排序对撞指针
Arrays.sort ( a );
List<List<Integer>> lists = new ArrayList <> ( );
//三层循环,用来拼对撞指针。
for (int i =0;i<a.length;i++){
if (i!=0&&a[i]==a[i-1]){
continue;
}
int newtarget = target-a[i];
for (int j = i+1;j<a.length;j++){
if (j!=i+1&&a[j]==a[j-1]){
continue;
}
int newtarget2 = newtarget-a[j];
int z= a.length-1;
for (int k = j+1;k<z;){
// 对撞指针进行判断
if (a[k]+a[z]==newtarget2){
List<Integer> list = new ArrayList <> ( );
list.add ( a[i] );
list.add ( a[j] );
list.add ( a[k] );
list.add ( a[z] );
lists.add ( list );
while (k<z&&a[k] == a[k + 1]) k++; //注意去重
while (k<z&&a[z] == a[z - 1]) z--;
k++;
z--;
} else if (a[k]+a[z]>newtarget2) {
z--;
}else {
k++;
}
}
}
}
System.out.println(lists);
执行结果:
执行用时:
总结:两数之和,三数之和,四数之和,这三道题有种异曲同工的味道,基本思想都是一样的,三数之和在两数之和的基础上,四数之和在三数之和的基础上。方法我推荐用对撞指针,灵活用时少。map,set等查找表也可以实现。方法多种多样。掌握思想最好。
2019-3-22