题目描述
题目描述:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?
找出所有满足条件且不重复的四元组。
给定数组 ints = [1, 0, -1, 0, -2, 2],和 target = 0。
输出:[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]].
解题思路
请先参考 算法精讲-leetcode15-三数之和为0 ,思路为leetcode15解题思路,其余细节在代码注释中。
代码示例
public class Test {
public static void main(String[] args) {
int[] ints = {1, 0, -1, 0, -2, 2};
int target = 0;
List<List<Integer>> lists = findFourNum(ints, target);
System.out.println(lists);
}
private static List<List<Integer>> findFourNum(int[] ints, int target) {
List<List<Integer>> lists = new ArrayList<>();
int length = ints.length;
if (length < 4){
return lists;
}
Arrays.sort(ints);
/*遍历时定义四个指针i,j,start,end,并且保证四个指针指向得数组索引一定不相同
其中i,j从左向右遍历,start,end从剩余部分两端向中间遍历
重要点1:去重需要注意:同一指针不可指向相同值的数据,则会产生重复数据
但是不同指针,在索引不同的前提下,值可以相同
比如:ints={0,0,0,0,1};target=1,则符合条件的集合为[0,0,0,1],该情况下:i==j==start
*/
for (int i=0; i< length - 3; i++){
/*
该处不可用这种方式判断,因为i后面有指针j,start,end
for循环中限制了i<length-3,在最后留出了剩余三个指针的位置,
如果以下面这种方式去重,则会遍历到i+1,侵占了j的位置,不满足上述:重要点1
if (ints[i] == ints[i+1]){
continue;
}*/
//去重
if (i > 0 && ints[i] == ints[i-1]){
continue;
}
//当最小结果都比target大时退出当前循环
if ((ints[i] + ints[i+1] + ints[i+2] +ints[i+3]) > target){
break;
}
//当最大结果都比target小时退出当前循环
if ((ints[i] + ints[length-3] + ints[length-2] + ints[length-1]) < target){
break;
}
//遍历j指针,从i+1开始,留下start、end两个指针的位置
for (int j = i+1; j< length - 2; j++){
//去重,与i指针去重注意点相同
if (j > i+1 && ints[j] == ints[j-1]){
continue;
}
//当最小结果都比target大时退出当前循环
if ((ints[i] + ints[j] + ints[j+1] + ints[j+2]) > target){
break;
}
//当最大结果都比target小时退出当前循环
if ((ints[i] + ints[j] + ints[length-2] + ints[length-1]) < target){
break;
}
//定义start、end两个指针,指向剩余部分的两端
int start = j+1;
int end = length - 1;
while (start < end){
//计算和
int sum = ints[i] + ints[j] + ints[start] +ints[end];
if (sum < target){
start++;
}else if (sum > target){
end--;
}else {
//去重
//为什么不再while循环的最开始去重,而当sum==target时才去重呢?
//假设ints={-1,0,1,2,3,3,3},target=6时
//当遍历到i=-1,j=1,start=2,end=3[指向末尾的3]
//如果此时在刚进入while循环进行去重的话,去重结果后将会是:i=-1,j=1,start=2,end=3[指向最开始的3]
//这样【-1,1,3,3】这个结果就无法获得
if (ints[start] == ints[start +1] && start+1<end){
start++;
continue;
}
//去重
if (ints[end] == ints[end-1] && end - 1 > start){
end--;
continue;
}
List<Integer> list = Arrays.asList(ints[i], ints[j], ints[start], ints[end]);
lists.add(list);
//移动指针
start++;
end--;
}
}
}
}
return lists;
}
}
运行结果
▄█▀█●各位同仁,如果我的代码对你有帮助,请给我一个赞吧,为了下次方便找到,也可关注加收藏呀
如果有什么意见或建议,也可留言区讨论