题:https://leetcode.com/problems/4sum-ii/description/
题目
Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero.
To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1.
Example:
Input:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]
Output:
2
Explanation:
The two tuples are:
- (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
- (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
思路
题目大意
解题思路
主要想法,将 数组A,数组B 相加 组成数组 AB。看数组C、D中是否有元素之和 CDsum,-CDsum在数组AB中。
各方法的不同点在于如何判断 CDsum。
方法 1 time O(n3) 会超时
count 为 组合次数,初始化为 0。
将 数组A,数组B 的每个元素 相加 组成数组 AB。遍历数组C、D元素,求和得到 CDsum,逐次查询-CDsum 在AB中出现的次数 t。count += t
time O(n3)
方法 2 time O(n2logn)
将AB排序,-CDsum中出现的次数 t = upperBound(-CDsum) - lowerBound(-CDsum)。count +=1。
方法3 timeO(n2)
将AB存入map中,key为AB value为出现的次数。count += Map.get(-CDsum)。
code
方法 1 time O(n3) 会超时
class Solution {
public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
List<Integer> preRes = new ArrayList<>();
for(int i = 0;i<A.length;i++)
for(int j = 0 ;j<B.length;j++)
preRes.add(A[i]+B[j]);
int count = 0 ;
for(int k = 0;k<C.length;k++)
for(int p = 0;p<D.length;p++){
int tmp = -(C[k]+D[p]);
for(int i = 0;i<preRes.size();i++){
if(tmp == preRes.get(i)) count++;
}
}
return count;
}
}
方法 2 time O(n2logn)
class Solution {
public static int lowerBound(int []nums,int l,int r,int target){
while(l<r){
int m = (l+r)/2;
if(nums[m]>=target) r= m;
else l = m +1;
}
return l;
}
public static int upperBound(int []nums ,int l,int r, int target){
while(l<r){
int m = (l+r)/2;
if(nums[m]<=target) l = m+1;
else r = m;
}
return l;
}
public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
int []preResArr = new int[A.length*B.length];
int t = 0;
for(int i = 0;i<A.length;i++)
for(int j = 0 ;j<B.length;j++)
preResArr[t++] = A[i]+B[j];
int count = 0 ;
Arrays.sort(preResArr);
for(int k = 0;k<C.length;k++)
for(int p = 0;p<D.length;p++){
int tmp = -(C[k]+D[p]);
count += Solution.upperBound(preResArr,0,preResArr.length,tmp) - Solution.lowerBound(preResArr,0,preResArr.length,tmp);
}
return count;
}
}
方法3 timeO(n2)
class Solution {
public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
Map<Integer,Integer> preResMap = new HashMap<>();
for(int i = 0; i<A.length;i++)
for(int j = 0; j<B.length; j++){
int tmp = A[i] + B[j];
if(!preResMap.containsKey(tmp)) preResMap.put(tmp,1);
else
preResMap.put(tmp,preResMap.get(tmp)+1);
}
int count = 0;
for(int i = 0;i < C.length; i++)
for(int j = 0;j < D.length;j++){
int tmp = -(C[i]+D[j]);
if(preResMap.containsKey(tmp)) count += preResMap.get(tmp);
}
return count;
}
}