其实这道题就是求2数之和,和3数之和的衍生吧,核心算法还是双指针; 暴力解法就不再说了:排序+暴力+set去重;
直接上:排序+双指针+去重
大致思路如上图,如果要详细算法过程,可以就看看两数之和和三数之和。 代码实现:
class Solution {
public static List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> lists =new ArrayList<>();
int n=nums.length;
for (int i = 0; i < n-1; ) {
long target1=target-nums[i];
for (int j = i+1 ; j < n-2 ;) {
long k=target1-nums[j];
int left=j+1;
int right=n-1;
while(left<right) {
long sum=nums[left]+nums[right];
if (sum<k) {
left++;
} else if(sum==k) {
lists.add(new ArrayList(Arrays.asList(nums[i],nums[j],nums[left],nums[right])));
left++;
right--;
while(left<right&&nums[right]==nums[right+1]) {
right--;
}
while (left<right&&nums[left]==nums[left-1]) {
left++;
}
} else {
right--;
}
}
j++;
while(j<n&&nums[j]==nums[j-1]) {
j++;
}
}
i++;
while(i<n&&nums[i]==nums[i-1]) {
i++;
}
}
return lists;
}
}
官方实现:
class Solution
{
public List<List<Integer>> fourSum(int[] nums, int target)
{
List<List<Integer>> ret = new ArrayList<>();
// 1. 排序
Arrays.sort(nums);
// 2. 利⽤双指针解决问题
int n = nums.length;
for(int i = 0; i < n; ) // 固定数 a
{
// 三数之和
for(int j = i + 1; j < n; ) // 固定数 b
{
// 双指针
int left = j + 1, right = n - 1;
long aim = (long)target - nums[i] - nums[j];
while(left < right)
{
int sum = nums[left] + nums[right];
if(sum > aim) right--;
else if(sum < aim) left++;
else
{
ret.add(Arrays.asList(nums[i], nums[j], nums[left++],
nums[right--]));
// 去重⼀
while(left < right && nums[left] == nums[left - 1])
left++;
while(left < right && nums[right] == nums[right + 1])
right--;
}
}
// 去重⼆
j++;
while(j < n && nums[j] == nums[j - 1]) j++;
}
// 去重三
i++;
while(i < n && nums[i] == nums[i - 1]) i++;
}
return ret;
}
}
这里最难的是去重和越界细节的去除,一定要画图和调试代码,找出问题。