找到数组中的最大值,该值是其他3个值的总和

时间:2014-04-22 05:30:34

标签: arrays algorithm

给定一个非常大的整数数组,我需要找到a4的最大值,这样:

a4 = a1 + a2 + a3

其中ai是数组中的所有值。

我该怎么做?

注意:使用4 for循环不是理想的解决方案。

3 个答案:

答案 0 :(得分:13)

有一个简单的(预期的)O(n ^ 2)解决方案:

  1. 遍历所有数组元素对(a,b)并将其总和存储在哈希表中。
  2. 遍历所有候选对(a4,a1)并检查a4 - a1是否在表中。所有有效a4的最大值是解决方案。当然你应该从最大到最小处理a4,但这并不会影响渐近。
  3. 如果你想避免多次使用一个元素,你需要在哈希表中存储一些额外的信息,这样你就可以过滤掉快速与a1或a4一致的对。

    如果数组中的整数是有界的(max - min< = C),那么知道使用离散傅立叶变换(使用FFT可解)可以实现O(n + C log C)可能是有用的。

答案 1 :(得分:2)

首先,您应该升序对数组进行排序。然后从数组的最后一个(最大)成员开始。 例如,对于[1,2,3,777,999,111,665],您已经sortArray = {1,2,3,111,665,777,999} 然后选择999作为a4并尝试与其他成员一起创建它。因此,您应该选择a3并尝试创建(999 - 777)= 222作为a1 + a2,因为您的数组已排序,您只需要考虑子阵列{1,2,3,111}。如果没有满足此条件的对,请尝试下一个最大成员(777)并重试以上场景以找到解决方案

答案 2 :(得分:0)

根据@Niklas的回答,我用Java编写了以下程序。

public static int sumOfThree(int [] arr) {
    int arrlen = arr.length;
    int arrijv [][] = new int [arrlen * (arrlen - 1) / 2][3];
    int arrijvlen = 0;

    quickSortInDescendingOrder(arr, 0, arrlen - 1); // sorts array into descending order

    System.out.println(Arrays.toString(arr));

    // populates array with sum of all pair values
    for (int i = 0; i < arrlen - 1; i++) {   
        for (int j = i + 1; j < arrlen; j++) {
            //  if ((arr[i] + arr[j]) < arr[0]) {       // can be added if no negative values
            arrijv[arrijvlen][0] = i;
            arrijv[arrijvlen][1] = j;
            arrijv[arrijvlen][2] = arr[i] + arr[j];
            arrijvlen++;
            //  }
        }
    }

    System.out.print('[');
    for (int i = 0; i < arrijvlen; i++) {
        System.out.print(arrijv[i][2] + " ");
    }
    System.out.print("]\n");

    // checks for a match of difference of other pair in the populated array 
    for (int i = 0; i < arrlen - 1; i++) {
        for (int j = i + 1; j < arrlen; j++) {
            int couldBeA4 = arr[i];
            if(isAvailable(arrijv, arrijvlen, couldBeA4 - arr[j], i, j)){
                System.out.println(" i3-" + j + " i4-" + i);
                return couldBeA4;
            }
        }
    }

    return -1;
}

private static boolean isAvailable(int[][] arrijv, int len, int diff, int i, int j) {
    boolean output = false;

    // returns true if the difference is matched with other combination of i,j
    for (int k = 0; k < len; k++) {
        if (arrijv[k][2] == diff) {
            int pi = arrijv[k][0];
            int pj = arrijv[k][1];

            if (pi != i && pi != j && pj != i && pj != j) {
                System.out.print("i1-" +  pj + " i2-" + pi);
                output = true;
                break;
            }
        }
    }
    return output;
}


private static void quickSortInDescendingOrder(int[] array, int low, int high) { // solely used for sorting input array into descending array
    if (low < high) {
        int partition = getPartitionIndex(array, low, high);
        quickSortInDescendingOrder(array, low, partition);
        quickSortInDescendingOrder(array, partition + 1, high);
    }
}

private static int getPartitionIndex(int[] arr, int lo, int hi) { 
    int pivot = arr[(lo + hi) / 2]; 

    while (true) {
        while (arr[lo] > pivot) {
            lo++;
        }

        while (arr[hi] < pivot) {
            hi--;
        }

        if (arr[lo] == arr[hi]) {   // can be removed if no duplicate values
            return lo;
        } else if (lo < hi) {
            int temp = arr[lo];
            arr[lo] = arr[hi];
            arr[hi] = temp;
        } else {
            return hi;
        }
    }
}

请确认其有效并建议进一步改进。