4-SUM的二次算法

时间:2013-02-06 15:11:09

标签: algorithm

4-SUM如下: 给定N个不同整数的数组,找到4个整数a,b,c,d,使得a + b + c + d = 0。 我可以提出一种使用二次算法求解3-SUM问题的立方算法。对于4-SUM,我们能做得比立方更好吗?

4 个答案:

答案 0 :(得分:16)

是的,你可以。遍历所有数字对并存储它们的总和(并且还存储哪些数字给出该总和)。之后,每次总结检查是否在您所拥有的金额中找到了否定。使用散列可以达到二次复杂度,使用std :: map,您将达到O(n^2*log(n))

编辑:为了确保不会多次使用数字,最好存储索引而不是每个总和的实际数字。另外,由于给定的总和可能由多个对形成,因此您必须使用散列多图。考虑到总和X = a1 + a2的数字不同,总和-X最多可以使用a1形成一次,并且一次使用a2,因此对于给定的总和{{1}你将不得不迭代最多3对,给予X总和。这仍然是不变的。

答案 1 :(得分:7)

对于使用O(N ^ 2)额外内存的此问题,还有一个O(N ^ 2)算法。

1-生成O(N ^ 2)中的所有成对和,并将对(a_i,a_j)存储在哈希表中,并使用它们的和的绝对值作为哈希表的关键字(a_i和a_j是两个不同数量的输入数组)

对表进行2次迭代,找到一个具有四个不同元素的负数和正数之和的键,返回作为答案

如果您不想使用哈希表,还有其他选择。由于您的数字是整数,您可以使用类似基数排序(有O(N ^ 2)个元素的内容对总和列表中元素的线性时间内的所有总和列表进行排序总和清单)。

答案 2 :(得分:1)

为4和问题分配代码,这将使您的二次时间复杂度降低。您可以使用任何给定的总和号运行该程序。在您的情况下,您希望总和为零,因此在函数参数中传递0。这个想法是,我们可以预先计算a + b的总和,然后先存储在地图中(如果地图中不存在),然后我们可以执行c + d并检查目标-(c + d)是否在地图中

import java.util.*;

public class FourSumPractice {
    public List<List<Integer>> quadTuple(int[] arr, int len, int sum){
    Map<Integer, Set<List<Integer>>> map = new HashMap<>();
    Set<List<Integer>> res = new HashSet<>();

    for (int i = 0; i < len - 1; i++) {
        for (int j = i + 1; j < len; j++) {
            int requiredSum = sum - (arr[i] + arr[j]);
            if(map.containsKey(requiredSum)){
                for (List<Integer> l : map.get(requiredSum)) {
                    int x = l.get(0);
                    int y = l.get(1);

                    if((x != i && x != j) && (y != i && y != j)){
                        List<Integer> quard = Arrays.asList(arr[i], arr[j], arr[x], arr[y]);
                        Collections.sort(quard);
                        res.add(quard);
                    }
                }
            }
            map.putIfAbsent(arr[i] + arr[j], new HashSet<>());
            map.get(arr[i] + arr[j]).add(Arrays.asList(i,j));
        }
    }
    return new ArrayList<>(res);
}

public static void main(String[] args)
{
    int[] A = { -10, 30, -15, -5, -5, -25, 0, 10, 51 };
    int sum = 0;
    FourSumPractice obj = new FourSumPractice();
    List<List<Integer>> l = obj.quadTuple(A, A.length, sum);
    for(List<Integer> sub:l){
        for(int i : sub){
            System.out.print(" "+ i);
        }
        System.out.println(" ");
       }
    }
}

答案 3 :(得分:-1)

对于每个索引i和j,在multimap中添加(S [i] + S [j])(多图bcz sum可以从不同的整数复制)并检查multimap是否包含总和 - (S [i] + S [J])。如果是,则添加到结果集。

void fourSUM(vector<int> array)
{
unordered_set<vector<int>> result;   // set to avoid duplicate results 
multimap<int,pair<int,int>> twosum_map;

for(unsigned int i=0; i< array.size();i++)
{
    for(unsigned int j=i+1; j< array.size();j++)
    {
        // insert sum in multimap
        twosum_map.insert(make_pair(array[i]+array[j],make_pair(i,j)));

        // look for -ve sum in multimap
        int lookfor = -(array[i]+array[j]);
        std::pair <std::multimap<int,pair<int,int>>::iterator, std::multimap<int,pair<int,int>>::iterator> ret;
        ret = twosum_map.equal_range(lookfor);

        for(std::multimap<int,pair<int,int>>::iterator it = ret.first; it != ret.second; it++)
        {
            vector<int> oneresult;
            oneresult.push_back(array[i]);
            oneresult.push_back(array[j]);
            oneresult.push_back(array[it->second.first]);
            oneresult.push_back(array[it->second.second]);
            result.insert(oneresult); // this avoids duplicate results 
        }
    }
}


// Display Result 
for(set<vector<int>>::iterator it=result.begin();it != result.end();it++)
{
    for( vector<int>::const_iterator  vit = it->begin(); vit != it->end(); vit++)
    {
        cout << *vit << " ";
    }
    cout << endl;
}
}

在multimap中插入/查找是log(n)。 set中的插入是log(n)。

复杂度O(n ^ 2 * log(n))。