Mdoify LIS这样一个元素大于之前所有元素的总和

时间:2016-12-24 14:45:09

标签: algorithm sorting set dynamic-programming lis

  

假设一个数组= {2,5,7,8,10}。您需要找到最长增加子序列的长度,以使元素不小于它之前所有元素的总和。

在这种情况下,答案可以是{2,5,7},{2,5,8}或{2,8,10}。所以长度= 3
这很容易在O(n ^ 2)中解决。由于LIS长度可以在O(n log n)中找到。因为问题只是询问长度,所以,我认为这个问题在O(n log n)中也是可以解决的。但是我该怎么做呢?

2 个答案:

答案 0 :(得分:0)

  1. 有一个O(N^2)动态编程解决方案,如:

    • f(i, j)为“正确”子序列以最后i个元素之一结尾且由j个元素组成的最小总和。

    • 基本情况为f(0, 0) = 0(空前缀,无元素)

    • 转换为f(i, j) -> f(i + 1, j)(不添加新元素)和
      f(i, j) -> f(i + 1, j + 1) if a[i] > f(i, j)(如果我们可以的话,将i - 元素添加到子序列的末尾。

  2. 这种解决方案的正确性是不言而喻的。

    1. 一个很酷的事实:让A成为k元素的“正确”子序列。比A的最后一个元素不小于max(1, 2^(k-2))(证据:k = 1k = 2的情况。现在我们可以使用归纳和{{1}的事实}})

    2. 因此,1 + sum i = 0 .. k of 2^k = 2^(k+1)在上述动态编程解决方案中的范围超过j,因此它适用于0..log MAX_A + C

    3. O(N * log MAX_A)不是O(N * log MAX_A),但此解决方案可以用于实际目的。

答案 1 :(得分:0)

实际上你根本不需要DP解决方案 首先按非递减顺序对数字进行排序。并从左到右循环。跟踪当前的总和 如果下一个数字不小于总和,则将其添加到LIS。否则进入下一个号码 可以证明贪婪的解决方案是最佳解决方案。自己证明;)