簡體   English   中英

找到兩個具有最大總和的數字,該數字也是數組中的元素

[英]Find two numbers that have the maximum sum which is also an element in the array

我最近在接受采訪時得到了這個問題:

給定一個數組,找到兩個具有最大總和的數字,該數字也是數組中的一個元素。

輸入: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)時間復雜度。 有人有更好的算法嗎?

這是我能想到的最快的。 由於列表已排序,因此您向后工作,嘗試查找是否有任何對加起來是數組中的最大剩余( 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到M范圍內的整數,那么您可以通過以下方式在O(Mlog(M))中執行此操作:

  1. 計算值的直方圖
  2. 使用快速傅立葉變換執行卷積
  3. 尋找卷積中存在的最大值

示例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)算法效率低,因此這僅在值有限時才有用。

如果您首先對數組進行排序,則可以按升序逐對檢查,添加兩個連續的數字並檢查它是否包含在數組中。

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)
{

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM