algorithm - 最大化输入中不超过 k 个连续元素的列表总和

标签 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;
}

最佳答案

O(NK) dynamic programming解决方案相当简单:

A[i] 为左侧受非k-连续约束约束的元素的最佳总和(假设我们要删除 >i-th 元素也是如此)。

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

A[i] = 0;
for j = 1 to k
  A[i] = max(A[i], A[i-j])
A[i] += input[i]

最后,只需查看 A 中的最后 k 个元素,将元素添加到每个元素的右侧,然后选择最好的一个。

但这太慢了。

让我们做得更好。

因此,A[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]

那里有很多冗余 - 由于 A[i],我们已经从索引 i-1i-K 中知道了最好的信息。 s 计算,但随后我们在 A[i+1] 中再次找到除了 i-K(使用 i)之外的所有计算中最好的。

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

我交换了问题的位置,使其变得稍微简单一些 - 我没有找到剩余元素的最大值,而是找到了删除元素的最小值,然后返回总和 - 删除的总和

高级伪代码:

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

关于algorithm - 最大化输入中不超过 k 个连续元素的列表总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19333450/

相关文章:

sql-server - 在 linked in 或 fb 中搜索如何运作?

algorithm - 归并排序lg(n)+1中递归树的高度怎么来的

C++ 记住要做的工作(算法)

python - 一旦进入状态,如何不脱离状态?

algorithm - 左子树的深度小于右子树的深度

c - 哈希表搜索和移动过去已删除的项目

algorithm - 算法解决方案的模糊/近似检查

algorithm - 大 O 符号的替代定义

java - 方法返回整数数组中奇数的个数

c++ - 迭代循环中的所有 (i,j) 元素