Leetcode 之 4Sum II

题目描述:
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:
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

相比4Sum这道题简单了不少,一开始看错了题目要求,以为要把所有组合都找出来,这样倒是比原题麻烦一点儿,但思路还算简单:
如果是暴力强解,复杂度应该是O(n^4),但咱们可以把A,B和C,D两两组合起来,再去找答案,这样就降低成了O(n^2)
先将A+B的所有组合,保存到一个map里,key是两者的sum,value是index的组合。 C+D一样操作。
再遍历A+B的map的key值,去找C+D的map的key值中有没有 A+B key值的相反数,有的话保存组合到list里。

代码如下:

public List<List<Integer>>fourSumII(int[]A,int[]B,int[]C,int[]D){
        List<List<Integer>>L=new ArrayList<List<Integer>>();
        List<Integer>l;
        HashMap<Integer,HashSet<int[]>>map1=new HashMap<Integer,HashSet<int[]>>(),map2=new HashMap<Integer,HashSet<int[]>>();

        HashSet<int[]>set;      
        int[]temp;
        int sum;
        for(int i=0;i<A.length;i++){
            for(int j=0;j<B.length;j++){
                sum=A[i]+B[j];
                if(map1.containsKey(sum)){
                    set=map1.get(sum);
                }
                else
                    set=new HashSet<int[]>();
                temp=new int[2];

                temp[0]=i;
                temp[1]=j;
                set.add(temp);
                map1.put(sum, set);

            }
        }

        for(int i=0;i<C.length;i++){
            for(int j=0;j<D.length;j++){
                sum=C[i]+D[j];
                if(map2.containsKey(sum)){
                    set=map2.get(sum);
                }
                else
                    set=new HashSet<int[]>();
                temp=new int[2];
                temp[0]=i;
                temp[1]=j;
                set.add(temp);
                map2.put(sum, set);
            }
        }
        HashSet<int[]>rest;

        for(int sum1:map1.keySet()){
            if(!map2.containsKey(-sum1))continue;

            rest=map2.get(-sum1);
            for(int[]h1:map1.get(sum1)){
                for(int[]h2:rest){
                    l=new ArrayList<Integer>();
                    for(int i:h1)l.add(i);
                    for(int i:h2)l.add(i);
                    L.add(l);
                }
            }
        }
        return L;
    }

题目的真实要求是找出组合的数目,这样就稍微简单一点了,
A+B,C+D的操作类似上述,但value值保存的是key值对应的个数。
再去遍历,总和等于A+Bmap的key值个数乘以C+Dmap中-key对应的个数。

代码如下:

public int fourSumII2(int[]A,int[]B,int[]C,int[]D){
        HashMap<Integer,Integer>m1=new HashMap<Integer,Integer>();
        HashMap<Integer,Integer>m2=new HashMap<Integer,Integer>();
        int sum=0,times;
        for(int i=0;i<A.length;i++){
            for(int j=0;j<B.length;j++){
                sum=A[i]+B[j];
                if(m1.containsKey(sum)){
                    times=m1.get(sum);
                    times++;
                    m1.put(sum, times);
                }
                else
                    m1.put(sum, 1);
            }
        }       
        for(int i=0;i<C.length;i++){
            for(int j=0;j<D.length;j++){
                sum=C[i]+D[j];
                if(m2.containsKey(sum)){
                    times=m2.get(sum);
                    times++;
                    m2.put(sum, times);
                }
                else
                    m2.put(sum, 1);
            }

        }
        int total=0;    
        for(int p1:m1.keySet()){
            if(m2.containsKey(-p1)){
                total+=m1.get(p1)*m2.get(-p1);
            }
        }
        return total;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值