来自数组中N个元素的绝对差的最大和

这实际上不是一项作业,而是一种练习和优化,但这似乎是此类问题的最佳部分。

这是一个动态编程问题,内容如下:

-给出N个元素的未排序数组,从中选择K个元素,以使它们的绝对差最大。

在此计算相邻元素之间的绝对差。因此,如果我们有一个由5个元素组成的数组:1 5 3 2 1,且k = 3,则绝对差为:

1 5 3 = | 5-1 | + | 3-5 | = 6

1 5 2 = | 5-1 | + | 2-5 | = 7

1 5 1 = [5-1 | + | 1-5 | = 8

1 5 1最大,需要1 8 1

到目前为止,我一直在尝试通过找到K个数字的所有可能组合并递归然后返回最大(蛮力)来解决这个问题。

这显示了一个可怕的想法,因为例如当尝试使用N = 50和k = 25的数组时,存在1.264106064E + 14个组合。

我使用的递归是一种简单的递归,用于从数组中打印所有K位整数,而不是打印它们,而是将它们保存在数组中:

static void solve(int[] numbers,int k,int startPosition,int[] result) {
        if (k == 0) {
            System.out.println(absoluteDifferenceSum(result));
            return;
        }
        for (int i = startPosition; i <= numbers.length - k; i++) {
            result[result.length - k] = numbers[i];
            solve(numbers,k - 1,i + 1,result);
        }
    }

我想要实现的是最佳复杂度(我想这里不能低于O(n ^ 2),但是我没有主意,也不知道如何开始。对您有所帮助!

yangjing314 回答:来自数组中N个元素的绝对差的最大和

通常,我们可以使用幼稚的O(n^2 * k)公式,其中f(i,k)代表在选择中第k个元素最右边时选择i个元素的最佳结果,

f(i,k) = max(
  f(j,k - 1) + abs(Ai - Aj)
)
for all j < i

我们可以扩展到

  max( f(j,k - 1) + Ai - Aj )
= Ai + max(f(j,k - 1) - Aj)

when Ai >= Aj

  max( f(j,k - 1) + Aj - Ai )
= -Ai + max(f(j,k - 1) + Aj)

when Ai < Aj

由于正确的求和数独立于Ai,因此我们可以构建一个树,其中的节点既存储f(j,k - 1) - Aj,又存储f(j,k - 1) + Aj。另外,我们将在每个节点中存储每个子树的两个最大值。我们需要O(k)树。当我们到达最后一个元素时,我们跳过对k = 2的树的检查:

1

5 -> 4 -> (-1,9)

3 -> 2 -> (-1,5)

2 -> 3 -> (-1,5)

3 -> (-3,5)

tree for k = 2 so far:

   3 (-1,5)
  /         \
2 (-1,5)   5 (-1,9)

1 is less than 3 so we first add -1
to the max for the right subtree
stored for f(j,k - 1) + Aj

-1 + 9 = 8
(note that this represents {1,5,1})

then we continue left in the tree
and compare 8 to a similar calculation
with node 2: -1 + 5 = 4
(note that this represents {5,2,1})

通过这种方式,我们可以将时间复杂度降低为O(n log n * k),且空间为O(n * k)

本文链接:https://www.f2er.com/3136465.html

大家都在问