问题:
给定一个包含 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] ]
思路:
排序加指针 先排除不可能的情况: 情况一、数组元素少于四个或者数组为空; 情况二、数组中最小的四个元素之和大于目标值; 情况三、数组中最大的四个元素之和小于目标值;
先排序,然后用四个指针三层循环解决问题。第一,第二个指针指向已排好序的第一,第二个元素,第三个指针指向第三个元素,第四个指针指向最后一个元素。第一层循环:第一个指针从0号元素移动到 length-4 号元素;第二层循环:第二个指针从1号元素移动到 length-3 号元素;第三层循环:1234指针之和大于目标值则第四个指针左移,若小于目标值则第三个指针右移,移动期间严格控制第四个指针在第三个指针右边。
额外条件:四元组不可重复,因此指针在移动的过程中需要判断下一元素是否和当前元素值相等,如果相等指针需要继续右移或者左移(左移情况针对最后一个指针)。
代码:
public static List
<List
<Integer>> fourSumPlus(int[] nums
, int target
) {
List
<List
<Integer>> ansList
= new ArrayList<>();
if (nums
== null
|| nums
.length
< 4) {
return ansList
;
}
Arrays
.sort(nums
);
int length
= nums
.length
;
int left
, right
, sum
;
for (int i
= 0; i
< length
- 3; i
++) {
if (i
> 0 && nums
[i
] == nums
[i
- 1]) {
continue;
}
if (nums
[i
] + nums
[i
+ 1] + nums
[i
+ 2] + nums
[i
+ 3] > target
) {
break;
}
if (nums
[i
] + nums
[length
- 3] + nums
[length
- 2] + nums
[length
- 1] < target
) {
continue;
}
for (int j
= i
+ 1; j
< length
- 2; j
++) {
if (j
> i
+ 1 && nums
[j
] == nums
[j
- 1]) {
continue;
}
if (nums
[i
] + nums
[j
] + nums
[j
+ 1] + nums
[j
+ 2] > target
) {
break;
}
if (nums
[i
] + nums
[j
] + nums
[length
- 2] + nums
[length
- 1] < target
) {
continue;
}
left
= j
+ 1;
right
= length
- 1;
while (left
< right
) {
sum
= nums
[i
] + nums
[j
] + nums
[left
] + nums
[right
];
if (sum
== target
) {
ansList
.add(Arrays
.asList(nums
[i
], nums
[j
], nums
[left
], nums
[right
]));
while (left
< right
&& nums
[left
] == nums
[left
+ 1]) {
left
++;
}
left
++;
while (left
< right
&& nums
[right
] == nums
[right
- 1]) {
right
--;
}
right
--;
} else if (sum
< target
)
left
++;
else right
--;
}
}
}
return ansList
;
}
时间复杂度:
时间复杂度:O(n3),其中 n 是数组的长度。排序的时间复杂度是 O(n log n),枚举四元组的时间复杂度是 O(n3),所以总时间复杂度是O(n3)。