18.四数之和
方法:排序+双指针
先对数组进行排序,使用两重循环分别枚举前两个数,然后在两重循环枚举到的数之后使用双指针枚举剩下的两个数
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
if(nums == null || nums.length < 4){
return ans;
}
Arrays.sort(nums);
int len = nums.length;
for(int i = 0; i < len - 3; i++){
//同一循环中,当前元素与上一个元素相同,则跳过当前元素
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
//确定第一个数之后,如果nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target
//说明此时剩下的三个数无论取什么值,四数之和一定大于target,因此退出第一重循环
if((long) nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target){
break;
}
//确定第一个数之后,如果nums[i] + nums[len-3] + nums[len-2] + nums[len-1] < target
//说明此时剩下的三位数无论取什么值,四数之和一定小于target,因此第一重循环直接进入下一轮,枚举nums[i+1]
if((long) nums[i] + nums[len-3] + nums[len-2] + nums[len-1] < target){
continue;
}
//使用两层循环分别枚举两个数,然后在两重循环枚举到的数之后使用双指针枚举剩下的两个数
for(int j = i + 1;j < len - 2 ; j++){
//同一循环中,当前元素与上一个元素相同,则跳过当前元素
if(j > i + 1 && nums[j] == nums[j - 1]){
continue;
}
//确定前两个数之后,如果nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target
//说明此时剩下的里两个数无论取什么值,四数之和一定大于target,因此退出第二重循环
if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
break;
}
//确定前两个数之后,如果nums[i] + nums[j] + nums[len-2] + nums[len -1] < target
//说明此时剩下的两个数无论取什么值,四数之后一定小于target,第二重循环直接进入下一轮,枚举nums[j+1]
if((long) nums[i] + nums[j] + nums[len-2] + nums[len -1] < target){
continue;
}
//在两重循环枚举到的数之后使用双指针枚举剩下的数
int left = j + 1,right = len - 1;
while(left < right){
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
if(sum == target){
ans.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 ans;
}
}