【问题标题】:What is the complexity of Longest increasing sub sequence algorithm without dynamic programming and how to compute it没有动态规划的最长递增子序列算法的复杂度是多少以及如何计算它
【发布时间】:2015-12-27 06:18:30
【问题描述】:

这是来自 LIS 的 GeeksForGeeks 的代码。

 /* To make use of recursive calls, this function must return
   two things:
   1) Length of LIS ending with element arr[n-1]. We use
  max_ending_here for this purpose
   2) Overall maximum as the LIS may end with an element
  before arr[n-1] max_ref is used this purpose.
  The value of LIS of full array of size n is stored in 
  *max_ref which is our final result */
int _lis( int arr[], int n, int *max_ref)
 {
/* Base case */
if (n == 1)
    return 1;

// 'max_ending_here' is length of LIS ending with arr[n-1]
int res, max_ending_here = 1; 

/* Recursively get all LIS ending with arr[0], arr[1] ... 
   arr[n-2]. If   arr[i-1] is smaller than arr[n-1], and 
   max ending with arr[n-1] needs to be updated, then 
   update it */
for (int i = 1; i < n; i++)
{
    res = _lis(arr, i, max_ref);
    if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here)
        max_ending_here = res + 1;
 }

// Compare max_ending_here with the overall max. And 
// update the overall max if needed
if (*max_ref < max_ending_here)
   *max_ref = max_ending_here;

// Return length of LIS ending with arr[n-1]
return max_ending_here;
}

// The wrapper function for _lis()
int lis(int arr[], int n)
 {
  // The max variable holds the result
int max = 1;

// The function _lis() stores its result in max
_lis( arr, n, &max );

// returns max
return max;
}

 /* Driver program to test above function */
int main()
 {
   int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
   int n = sizeof(arr)/sizeof(arr[0]);
   printf("Length of LIS is %d\n",  lis( arr, n ));
   return 0;
 }

这是树。如何通过它计算算法的复杂度?是否有一些适当的方法来计算此类算法的复杂度或程序员直观地计算它,并在应用动态编程后如何将复杂度降低到 0(n^2)

                 lis(4)   

             /       |      \
        lis(3)      lis(2)    lis(1)  
       /     \        /         
   lis(2)  lis(1)   lis(1) 
   /    
lis(1) 

【问题讨论】:

    标签: c++ c algorithm


    【解决方案1】:

    让输入大小n = f(n)

    的解的复杂度没有动态规划

    现在,观察复发:
    f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(1)
    其中递归 f(n-1) = f(n-2) + f(n-3) + ... f(1)

    显然,我们可以观察到 f(n) = 2*f(n-1)
    所以我们的紧凑递归关系是f(n) = 2*f(n-1)

    f(n) = 2*f(n-1)
    f(n-1) = 2*f(n-2)
    ...
    f(2) = 2*f(1)
    f(1) = 2*f(0)

    在上述方程中,将第i个方程乘以2^(i-1),然后将所有方程相加。我们显然有 f(n) = (2^n)*f(0) = O(2^n)

    因此复杂度是指数级的 = O(2^n)

    现在让我们看看使用动态编程时会发生什么。当我们使用 DP 时,我们会在计算后保存 f(n),这样我们就不会在递归中再次计算它。这给我们留下了:
    f(n) = f(n-1) + f(n-2) + ... f(1)
    但是这一次当 f(n-1) 的递归调用计算 f(n-2)、f(n-3) 等时,我们不必在计算 f(n) 时重新计算它。

    所以现在,f(n) = n + (n-1) + (n-2) + ... 1 这是O(n^2)
    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-04-26
      • 1970-01-01
      • 2016-05-02
      • 2016-08-12
      • 2011-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多