找到所有可能数字组的最大值和最小值之间的最小差异

时间:2013-04-09 18:39:26

标签: algorithm math data-structures

每个都有 n k 大小的数组。

a0[0],a0[1],......a0[k-1]
a1[0],a1[1],......a1[k-1]
.
.
.
an-1[0],an-1[1], .... an-1[k-1]

根本没有重复项,所有数组都已排序。

现在,通过从每个数组中随机取任何值来构造一组大小 n 。 例如,一个这样的集可以是{a0[0],a1[3],a2[2],.... an-1[k-1]}

我的目标是找出所有可能集合中的最小和最大元素,使得最小值和最大值之间的差异最小。

示例(k = 3,n = 3)

[3 7 11]
[1 12 15]
[4 19 21]

所以在数学上会有27个这样的集合

(3 1 4) (3 12 4) (3 15 4)
(3 1 19) (3 12 19) (3 15 19)
(3 1 21) (3 12 21) (3 15 21)

(7 1 4) (7 12 4) (7 15 4)
(7 1 19) (7 12 19) (7 15 19)
(7 1 21) (7 12 21) (7 15 21)

(11 1 4) (7 12 4) (11 15 4)
(11 1 19) (7 12 19) (11 15 19)
(11 1 21) (7 12 21) (11 15 21)

在计算所有这些集合的最小值和最大值之后,我们可以得出结论:(3 1 4)是min(1)和max(4)之间的差值是全局最小值或最小值的集合。

因此我们将输出3作为全局最小差异,并输出相应的对(3 4)。如果有多个全局最小值,则将它们全部打印出来。请建议具有更好时间和空间复杂度的算法。我们不能采取蛮力的方法。

5 个答案:

答案 0 :(得分:1)

迭代所有n * k个元素。

假设我们当前元素的值为v。假设v是结果n元组中的最小值,让我们计算最小差异​​。

二进制搜索v在其他n - 1数组中的位置(因为它们已经排序,我们可以这样做),并注意到为了减少差异,最好选择最小的元素对于所有其他数组,大于或等于v。这正是二元搜索给我们带来的。

示例:

[3 7 11]
[1 12 15]
[4 19 21]

如果我们在第二个数组上取v = 1,那么我们将在第一个数组上选择3,在第二个数组上选择4。

复杂性为O(N * K * N * log(N)) = O(N^2 * log(N) * K)

答案 1 :(得分:1)

如果我理解正确,您希望找到其元素中最大差异全局最小的集合。 (我将称之为集合的范围)

从k集开始,每个集最初包含第一个数组中的一个元素。对于每个集合,最小值和最大值将等于元素本身。 对于您的示例{3},{7}和{11}。

然后你转到第二个数组。对于每个集合,您必须从该数组中选择一个最小化新范围的元素。理想情况下,您会选择一个不会增加范围的元素(但现在不可能)。如果无法做到这一点,请选择向两个方向展开集合的元素(加号和减号)。对于提供{1-3},{3-12},{1-7},{7-12},{1-11}和{11-12}的示例。从这些 2k 集中,您可以删除重叠的集。例如,与集合{1-3}相比,集合{1-7}将始终具有更大或相等的范围。您无需调查{1-7}集。你最终得到了集合{1-3}和{11-12}。

继续第三个数组,再次选择扩展每个集合范围的元素尽可能小。最终得到{1-4},{11-19}和{4-12}。然后只需选择范围最小的那个。

答案 2 :(得分:1)

该算法的复杂度为O(n * k * logn)

仅选择每行中的第一个元素,并创建最小堆和最大堆。

计算当前差异(= head(maxHeap)-head(minheap))

删除minHeap的头部(以及maxHeap中的相应元素),并将相应数组中的下一个元素(对应于删除的元素)添加到minHeap和maxHeap。

重复此过程,直到其中一个阵列中的所有元素都耗尽。

复杂性:您添加/删除nk元素并且更新最多需要O(n)时间。所以复杂性是O(nklogn)。

注意:这不完全是你的库存堆。 minHeap包含指向maxHeap中相同元素的指针,反之亦然。从minHeap中删除元素时,可以找到maxHeap的链接并将其删除。此外,只要特定元素的位置发生变化,就会对另一个堆中的链接进行适当的更改。

答案 3 :(得分:0)

将结果Set视为一个简单的1xn数组

[3]
[1]
[4]

其中全局差异为3(最小值为4,最小值为1)。

现在考虑Set的扩展定义,称之为MultiSet。 MultiSet是一个数组,其中每个元素包含一组有序的项。

[3 7 11]
[1 12 15]
[4 19 21]

我们可以通过每行的最大“最后”值与每行的最小“第一”值之间的差异来计算全局差异(称为“成本”)。在这种情况下,费用将是21(max(11,15,21))和1(min(3,1,4))之间的差异,即20。

现在,该过程将迭代MultiSet,直到我们使用以下算法达到最低成本:

  • 标识具有最低值的行。如果此行只有一个元素,则继续,否则考虑从该行中删除低于任何其他行的最低值的值的潜在成本降低。
  • 标识具有最高值的行。如果此行只有元素然后继续,否则考虑从该行中删除高于任何其他行的最高值的值的潜在成本降低。
  • 删除上面标识的值并继续下一个最高/最低项目。 -
  • 如果最低值和最高值都在单项行中,则成本已最小化。

为了演示在给定的示例中,通过删除1的最低值(MultiSet中最低值低于任何其他行最小值)或减少的最低值,可以将原始成本减少到18。从最后一行中删除1921的最高值(MultiSet中的最高值,高于任何其他行的最大值,即15)。生成的MultiSet将是

[3 7 11]
[1 12 15]
[4]

第二次迭代让我们删除1215以将费用降低到10。

[3 7 11]
[1]
[4]

第三次也是最后一次迭代让我们删除711以将成本降低到3.在第三次迭代之后,不再能够最小化全局差异,从而达到解决方案。

复杂性?上限由O(n * m * log(n)* k)

组成

答案 4 :(得分:0)

代码:

private static ElementData calcMin(int[] n1Arr, int[] n2Arr, int[] n3Arr) {

    ElementData data = new ElementData();// added just to know which two elements algo has picked

    int[] mixArr = { n1Arr[0], n2Arr[0], n3Arr[0] };
    Arrays.sort(mixArr);
    int minValue = mixArr[2] - mixArr[0];

    data.setMinValue(minValue);
    data.setHighValue(mixArr[2]);
    data.setLowValue(mixArr[0]);

    int tempValue = 0;
    for (int n1 : n1Arr) {

        for (int n2 : n2Arr) {

            for (int n3 : n3Arr) {

                int[] mixArr1 = { n1, n2, n3 };
                Arrays.sort(mixArr1);

                tempValue = mixArr1[2] - mixArr1[0];
                if (minValue > tempValue) {
                    minValue = tempValue;

                    data = new ElementData();
                    data.setMinValue(minValue);
                    data.setHighValue(mixArr1[2]);
                    data.setLowValue(mixArr1[0]);
                }
            }
        }
    }
    return data;
}