[leetcode]4Sum

这道4Sum,如果用3Sum类似的方法,是O(n^3)的复杂度。现在使用O(n^2)的空间呢,能达到O(n^2)的时间复杂度。但实现起来坑还是不少,一是要去重,用了string来表示集合的key;二是不能同一个索引位置的数(num[i])出现两次,所以要做下标的检查;三是当左右相加等于target的时候,现在不能直接跳过大小一样的,因为同样大小的可能是a+b也可能是c+d,就要l++和r--递归来做。但用递归有可能爆栈(Runtime Error),就用了Stack来模拟递归。最终Java 1472ms过。

后来参考方勤的版本,如果用map来存sum=>pair,在只求解(而非全部解)的情况下,可以O(n^2)写得更简洁。

import java.util.*;
public class Solution {
    private ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
    private HashSet<String> ansSet = new HashSet<String>();
    private HashSet<String> posSet = new HashSet<String>();
    public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
        ans.clear();
        ansSet.clear();
        posSet.clear();
        Arrays.sort(num);
        int len = num.length;
        ArrayList<Pair> pairs = new ArrayList<Pair>();
        for (int i = 0; i < len; i++)
        {
            for (int j = i+1; j < len; j++)
            {
                pairs.add(new Pair(num[i], num[j], i, j));
            }
        }
        Collections.sort(pairs);
        Stack<Integer> stack = new Stack<Integer>();
        stack.push(0); stack.push(pairs.size()-1);
        while (!stack.empty())
        {
            int r = stack.pop();
            int l = stack.pop();
            if (l >= r) continue;
            String posKey = "" + l + "_" + r;
            if (posSet.contains(posKey)) continue;
            else posSet.add(posKey);
            int sum = pairs.get(l).sum + pairs.get(r).sum;
            if (sum < target)
            {
                stack.push(l+1);
                stack.push(r);
            }
            else if (sum > target)
            {
                stack.push(l);
                stack.push(r-1);
            }
            else // ==
            {
                if (pairs.get(l).aIdx != pairs.get(r).aIdx &&
                    pairs.get(l).aIdx != pairs.get(r).bIdx &&
                    pairs.get(l).bIdx != pairs.get(r).aIdx &&
                    pairs.get(l).bIdx != pairs.get(r).bIdx)
                {
                    // add to result;
                    ArrayList<Integer> arr = new ArrayList<Integer>();
                    arr.add(pairs.get(l).a);
                    arr.add(pairs.get(l).b);
                    arr.add(pairs.get(r).a);
                    arr.add(pairs.get(r).b);
                    Collections.sort(arr);
                    String key = "";
                    for (int k = 0; k < 4; k++)
                    {
                        key = key + arr.get(k) + "_";
                    }
                    if (!ansSet.contains(key))
                    {
                        ansSet.add(key);
                        ans.add(arr);
                    }
                }     
                stack.push(l);
                stack.push(r-1);
                stack.push(l+1);
                stack.push(r);
            }
        }
        return ans;
    }
}

class Pair implements Comparable<Pair>
{
    int a;
    int b;
    int sum;
    int aIdx;
    int bIdx;
    
    public Pair (int a, int b, int aIdx, int bIdx)
    {
        this.a = a;
        this.b = b;
        this.sum = a + b;
        this.aIdx = aIdx;
        this.bIdx = bIdx;
    }
    
    public int compareTo(Pair that)
    {
        return this.sum - that.sum;
    }
}

  

原文地址:https://www.cnblogs.com/lautsie/p/3350725.html