找到两个具有最大总和的数字,该数字也是数组中的元素

时间:2018-04-13 16:01:37

标签: java arrays algorithm

我最近在接受采访时得到了这个问题:

给定一个数组,找到两个具有最大总和的数字,该数字也是数组中的一个元素。

输入:6 10 12 34 41 16 输出:16

[更新]我的代码如下:

    public class Solution {
    public static int findMaximumNumbers(int a[])
    {
        Set<Integer> set=new HashSet<>();
        for(int n:a) set.add(n);
        Arrays.sort(a);
        int max=Integer.MIN_VALUE;
        for(int i=a.length-1;i>0;i--)
        {
            for(int j=i;j>=0;j--)
            {
                int sum = a[i] + a[j];
                if(set.contains(sum) && max<sum)
                   max=sum;
            }
        }
        return max;
    }

    public static void main(String[] args) {
        System.out.println( findMaximumNumbers(new int[]{ 6, 10, 12, 34, 40, 16, 41, 47, 74 }));
        System.out.println( findMaximumNumbers(new int[]{ 2, 25, 35, 40, 42, 60 }));
    }
}

该算法需要O(n ^ 2)时间复杂度。有人有更好的算法吗?

3 个答案:

答案 0 :(得分:0)

这是我能想到的最快的。由于列表已排序,因此您向后工作,尝试查找是否有任何对加起来是数组中的最大剩余(i循环)。它将尽可能快地短路,并给出正确的答案。在j循环中,当您达到的值小于目标的一半时,倒计时停止(不使用迭代无法累加到目标的剩余值)。但我希望有人可以做得更好。 OP代码将进行n*(n-1)/2次迭代,但即使没有解决方案,这个迭代也总会做得更少。

public static int findMaximumNumbers(int a[])
{
    Set<Integer> set=new HashSet<>();
    for(int n:a) set.add(n);
    Arrays.sort(a);
    if (a[0] == 0)
        return a[a.length-1];
    for(int i=a.length-1;i>0;i--)
    {
        int j = i-1;
        int m = a[i] / 2;
        while (j >= 0 && a[j] > m) {
            if (set.contains(a[i]-a[j]))
                return a[i];
            j--;
        }
    }
    return -1;
}

答案 1 :(得分:0)

如果您的数字是1到M范围内的整数,那么您可以通过以下方式在O(Mlog(M))中执行此操作:

  1. 计算值的直方图
  2. 使用快速傅里叶变换执行卷积
  3. 搜索卷积中存在的最大值
  4. 示例Python代码:

    import scipy.signal
    import time
    
    def hist(X):
        """Prepare a histogram of X"""
        h = [0]*(max(X)+1)
        for x in X:
            h[x] += 1
        return h
    
    A = [6, 10, 12, 34, 41, 16]
    H = hist(A)
    R = scipy.signal.fftconvolve(H,H)
    for x in sorted(A,reverse=True):
        if R[x] > 0.5:
            print x
            break
    else:
        print 'No solutions'
    

    关键是直方图的卷积是所有可能元素总和的直方图。

    当然,如果您有100个数字,其值在1到10 ** 100之间,那么这将比您的O(n ^ 2)算法效率低,因此这仅在值有限时才有用。 / p>

答案 2 :(得分:-1)

如果您首先对数组进行排序,则可以按升序逐对检查,添加两个连续数字并检查它是否包含在数组中。

int myArray[];

Arrays.sort(myArray);

int a = -1, b, highest = Integer.MIN_VALUE;
for(int i = 0; i < myArray.length - 1; i++) 
{
    int sum = myArray[i] + myArray[i + 1];

    int startCheck = i + 1;
    while(myArray[startCheck] < sum && startCheck < myArray.length)
        startCheck++;

    if(myArray[startCheck] == sum && sum > highest)
    {
        a = i;
        b = i + 1;
        highest = sum;
    }
}

// Found 2 elements whose sum is on the array
if(a != -1)
{

}