最大化列表总和,输入不超过k个连续元素

时间:2013-10-12 11:06:26

标签: algorithm

我有一个 N 数字的数组,我想只删除列表中的那些元素,这些元素在删除时会创建一个新的列表,其中不再有 K 数字对彼此。可以使用此限制创建多个列表。所以我只想要一个列表,其中剩余数字的总和最大,并且只作为输出打印的总和。

到目前为止,我提出的算法的时间复杂度为O(n ^ 2)。是否有可能为这个问题找到更好的算法?

Link to the question

这是我的尝试:

int main()
{
    //Total Number of elements in the list
    int count = 6;
    //Maximum number of elements that can be together
    int maxTogether = 1;

    //The list of numbers
    int billboards[] = {4, 7, 2, 0, 8, 9};

    int maxSum = 0;
    for(int k = 0; k<=maxTogether ; k++){
        int sum=0;
        int size= k;

        for (int i = 0; i< count; i++) {
            if(size != maxTogether){
                sum += billboards[i];
                size++;
            }else{
                size = 0;
            }
        }
        printf("%i\n", sum);
        if(sum > maxSum)
        {
            maxSum = sum;
        }
    }
    return 0;
}

3 个答案:

答案 0 :(得分:1)

O(NK) dynamic programming解决方案非常简单:

A[i]成为左边元素的最佳总和,不受{ - {1}} - 连续约束(假设我们也删除了k - 元素)

然后我们可以通过回顾i元素来计算A[i]

K

最后,只需查看A[i] = 0; for j = 1 to k A[i] = max(A[i], A[i-j]) A[i] += input[i] 中的最后一个k元素,将每个元素添加到每个元素并选择最佳元素。

但这太慢了。

让我们做得更好。

因此AA[i]A[i-1],...,A[i-2]A[i-K+1]中找到最佳结果。
因此,A[i-K]可以从A[i+1]A[i]A[i-1],...,A[i-2]找到最佳效果。

那里有很多冗余 - 由于A[i-K+1]的计算,我们已经从索引i-1i-K知道了最好的,但是我们发现除了A[i]以外的最好的那些i-K中再次iA[i+1]}。

因此,我们可以将所有这些存储在有序数据结构中,然后删除A[i-K]并插入A[i]。我的选择 - binary search tree找到最小值,以及circular array大小K+1树节点,这样我们就可以轻松找到我们需要删除的那个。

我交换了问题,使其稍微简单一点 - 而不是找到剩余元素的最大值,我发现删除元素的最小值,然后返回total sum - removed sum

高级伪代码:

for each i in input
  add (i + the smallest value in the BST) to the BST
  add the above node to the circular array
    if it wrapper around, remove the overridden element from the BST

// now the remaining nodes in the BST are the last k elements

return (the total sum - the smallest value in the BST)

运行时间:

O(n log k)

Java代码:

int getBestSum(int[] input, int K)
{
   Node[] array = new Node[K+1];
   TreeSet<Node> nodes = new TreeSet<Node>();
   Node n = new Node(0);
   nodes.add(n);
   array[0] = n;
   int arrPos = 0;
   int sum = 0;
   for (int i: input)
   {
      sum += i;
      Node oldNode = nodes.first();
      Node newNode = new Node(oldNode.value + i);
      arrPos = (arrPos + 1) % array.length;
      if (array[arrPos] != null)
         nodes.remove(array[arrPos]);
      array[arrPos] = newNode;
      nodes.add(newNode);
   }
   return sum - nodes.first().value;
}

getBestSum(new int[]{1,2,3,1,6,10}, 2)根据需要打印21

答案 1 :(得分:0)

f[i]成为前i个数字可以获得的最大总值,而不选择最后一个(即第i个)数字。然后我们有

f[i] = max{
           f[i-1],
           max{f[j] + sum(j + 1, i - 1) | (i - j) <= k}
          }

您可以使用类似heap的数据结构来维护选项,并在log(n)时间内获得最大值,保持全局delta或其他任何内容,并注意范围i - j <= k

答案 2 :(得分:0)

以下算法具有O(N * K)复杂度。

检查阵列的第1个K元素(0到K-1)。该地区最多可以有1个缺口 原因:如果有两个缺口,那么就没有任何理由可以得到更低的(更早的差距)。

For each index i of these K gap options, following holds true:  
 1. Sum upto i-1 is the present score of each option.  
 2. If the next gap is after a distance of d, then the options for d are (K - i) to K  

For every possible position of gap, calculate the best sum upto that position among the options.  
The latter part of the array can be traversed similarly independently from the past gap history.

进一步遍历阵列直到结束。

相关问题