题:https://leetcode.com/problems/4sum/
题目大意
从 数组nums ,从中选取 4个数,使得 4 数之和为 target。
思路
O(n3) 类似 3 sum
先取 2个数,然后 双指针方法
对于 重复的数字,可以使用 两种措施改进。
若 nums[i-1] == nums[i] 或 nums[j-1] == nums[j], 那么前面已经 遍历过 。
若 while(l<r && nums[r-1] == nums[r])
r–;
while(l<r && nums[l+1] == nums[l])
l++;
对双指针 跳过 重复
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList();
for(int i = 0 ; i < nums.length ; i++){
if(i > 0 && nums[i-1] == nums[i])
continue;
for(int j = i+1; j < nums.length ;j++){
if(j > i + 1 && nums[j-1] == nums[j])
continue;
int l = j+1;
int r = nums.length -1;
while(l < r){
int tsum = nums[i] + nums[j] + nums[l] + nums[r];
if(tsum == target){
List<Integer> eRes = new ArrayList();
eRes.add(nums[i]);
eRes.add(nums[j]);
eRes.add(nums[l]);
eRes.add(nums[r]);
res.add(eRes);
while(l<r && nums[r-1] == nums[r])
r--;
while(l<r && nums[l+1] == nums[l])
l++;
r--;
l++;
}
else if(tsum>target){
r--;
}else{
l++;
}
}
}
}
return res;
}
}
O(n2)
使用 map 记录 每tsum。
然后,每次抽 两个数,看对应数 是否在 map中,并使用 res.contains(eRes) 来 去除重复。
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList();
Map<Integer,List<Integer[]>> map = new HashMap();
for(int i = 0 ; i < nums.length ; i++){
for(int j = i + 1 ;j < nums.length ; j++){
int tsum = nums[i] + nums[j];
if(map.get(tsum) == null)
map.put(tsum,new ArrayList());
map.get(tsum).add(new Integer[]{i,j});
}
}
for(int i = 0 ; i < nums.length ; i++){
if(i > 0 && nums[i-1] == nums[i])
continue;
for(int j = i + 1 ;j < nums.length ; j++){
if(j > i + 1 && nums[j-1] == nums[j])
continue;
int remainder = target - nums[i] - nums[j];
if(!map.containsKey(remainder))
continue;
for(Integer[] iArr: map.get(remainder)){
int l = iArr[0];
int r = iArr[1];
if(j >= l)
continue;
List<Integer> eRes = new ArrayList();
eRes.add(nums[i]);
eRes.add(nums[j]);
eRes.add(nums[l]);
eRes.add(nums[r]);
if(!res.contains(eRes))
res.add(eRes);
}
}
}
return res;
}
}