更快的算法

时间:2012-04-06 13:38:17

标签: algorithm

我被告知编写如下算法 存在三个相同大小N的数组A [],B [],C []。找出所有可能的(i,j,k),使得A [i] + B [j] = C [k]。允许的最大时间复杂度为O(N ^ 2)。以下是我为O(N ^ 2)编写的算法

#include<stdio.h>

#define MAX 1000

struct sum
{
        int result;
        int i;
        int j;
};

int main()
{
        struct sum sum_array[MAX];
        int n=4;
        int a[] = {4,1,2,5};
        int b[] = {1,7,6,0};
        int c[] = {11,3,8,2};
        int k;
        int i,j;
        for(i=0;i<MAX;i++)
                sum_array[i].result=-1;
        for(i=0;i<n;i++)
        {
                for(j=0;j<n;j++)
                {
                        sum_array[a[i]+b[j]].result=a[i]+b[j];
                        sum_array[a[i]+b[j]].i=i;
                        sum_array[a[i]+b[j]].j=j;
                }
        }
        for(k=0;k<n;k++)
        {
                if(sum_array[c[k]].result==c[k])
                {
                        printf("<i,j,k> = <%d,%d,%d>\n",sum_array[c[k]].i,sum_array[c[k]].j,k);
                }
        }
        return 0;
}

我的问题是如何更快地完成?任何O(N * logN)或更好的算法?

此致 ARKA

4 个答案:

答案 0 :(得分:6)

最大答案大小为N ^ 3,因此无法实现更好的复杂性。 举个例子A = {1,1,1,1,1,1,1},B = {1,1,1,1,1,1} C = {2,2,2,2,2,2你接近的方法不会为上面的例子输出所有可能的三元组。

答案 1 :(得分:1)

如果您正在寻找一种组合或只是这些组合的数量,那么:

MAX成为数组ABC的最大元素。 我的解决方案是O(MAX log(MAX))

我正在描述没有细节的想法。

让我们A_count[x] =数组x中的元素数量AABC计算此类数组 它可以在线性时间内完成。

将数组A_countB_countC_count视为多项式。如果A[i] + B[j]总和为X,则A_count * B_count(乘以多项式)为coefficient[X]!= 0。

所以现在想法很简单。计算A_count * B_count并将其系数与C_count的系数进行比较。可以使用Discrete Fourier transformA_count * B_count中计算O(MAX log(MAX))

@edit,

上的例子
int A[] = {4,1,2};
int B[] = {1,0};
int C[] = {3,8,2};

让我们计算A_count,B_count,C_count

                 0, 1, 2, 3, 4, 5, 6, 7, 8
int A_count[] = {0, 1, 1, 0, 1};
int B_count[] = {1, 1}; 
int C_count[] = {0, 0, 1, 1, 0, 0, 0, 0, 1}

现在让我们计算A_count * B_count。简单的乘法算法:

for(int i=0; i<A_count_SIZE; i++)
    for(int j=0; j<B_count_SIZE; j++)
        mult_result[i+j] += A_count[i] * B_count[j];

但可以更快地完成(Discrete Fourier transform)。

int mult_result[] = {0, 1, 2, 1, 1, 1}

这意味着:

1 pair sums to 1
2 pairs sums to 2
1 pair sums to 3
1 pair sums to 4
1 pair sums to 5

答案 2 :(得分:0)

我认为你找不到比O(N 2 )更快的东西,只是因为你必须遍历每个B的所有A来获得所有数组元素的总和。仅此一项是O(N 2 ),阻止你获得更快的任何东西。

编辑:虽然,有一些优化要做。例如,您设置了sum_array[a[i]+b[j]].result = a[i]+b[j]。稍后您将测试密钥是否等于结果。它怎么可能是平等的呢?

答案 3 :(得分:0)

如果你想找到A[i]+B[j]=C[k]的三元组(i,j,k)的存在,那么它可以在O(n^2 logn)中完成。此外,您可以使用此方法找到此类三元组的数量。

  • 制作一个新数组D[],以便D保存每对AB的总和。这将使D = n ^ 2的大小。
  • 排序数组C.现在,binary search表示数组DC的所有值。时间复杂度为O(n^2 logn)

要计算三胞胎的数量,

  • 仅当lower bound中存在该值upper bound时才能查找C[]DD的值(可以使用下限函数返回的索引)。

    count + = upper_bound_index - lower_bound_index;

时间复杂度也是O(n^2 logn)