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;}
}