n  factorial

提起递归问题, 首先想到的是Fibonacci 和 n fractorial。为了提高算法效率, 我们常常避免使用递归。   fibonacci 可以通过DP的办法求解。因为Fibonacci 不仅具有overlapping subproblem, 而且还有最优子结构(optimal structure)。  但是n factorial 却不能使用DP办法解决。 下面给出具体原因。

n factorial :

n  factorial_第1张图片

def factorial(n):
	if n == 0: return 1
	return n*factorial(n-1)
Thus the problem of calculating  factorial(n)  depends on calculating the subproblem factorial(n-1) . This problem does  not  exhibit  overlapping  subproblems since  factorial is called exactly once for each positive integer less than n.

fibonacci

def fib(n):
	if n == 0: return 0
	if n == 1: return 1
	return fib(n-1) + fib(n-2)

计算过程如下:

fib(5)
fib(4) + fib(3)
fib(3) + fib(2) + fib(2) + fib(1)
fib(2) + fib(1) + fib(1) + fib(0) + fib(1) + fib(0) + fib(1)
fib(1) + fib(0) + fib(1) + fib(1) + fib(0) + fib(1) + fib(0) + fib(1)

对于那些无法使用DP的, 具有递归结构的问题, 如何去优化呢?

例如, 在这里, 求解n factorial:

对于n factorial , 我们可以使用迭代的办法:

n  factorial_第2张图片d


递归和迭代的比较如下:

n  factorial_第3张图片


虽然n factorial 不能使用动态规划, 但是当我们的问题成为求解某一个需要提前求解出 1!, 2!, 3!, ...., 以便日后使用的时候, 我们可以(勉强)使用动态规划。 可以在网上搜到:

#include 

using namespace std;

 

// Factorial bottom-up dynamic programming.

// In bottom-up programming, programmer

// has to do the thinking by selecting values

// to calculate and order of calculation.

// This problem is not a good example because

// this problem does not exhibit overlapping subproblems

// since factorial is called exactly once

// for each positive integer less than n.

int fact_dp_bu(int n)

{

    int result[n];

    if (n >= 0) {

        result[0] = 1;

        for(int i=1; i<=n; ++i) {

            result[i] = i * result[i-1];

        }

        return result[n];

    }

    else {

        return numeric_limits::min();

    }

}

 

// Factorial top-down dynamic programming

// In top-down programming, recursive

// structure of original code is preserved, but

// unnecessary recalculation is avoided.

int factorial[100];

int fact_dp_td(int n)

{

    if (n < 0)

        return numeric_limits::min();

 

    if (factorial[n] > 1)

        return factorial[n];

 

    if (n == 0 || n == 1) // base cases first

        return 1;

 

    factorial[n] = n * fact_dp_td(n-1);  // recursion case

 

    return factorial[n];

}

 

/**

 *  Computes the factorial of the nonnegative integer n.

 *  @pre  n >= 0.

 *  @post None.

 *  @param n The nonnegative integer to compute its factorial.

 *  @return The factorial of n; n is unchanged.

 */

int fact_recursion(int n)   // factorial recursion

{

    if (n == 0)

        return 1;                        // base case

    else

        return n * fact_recursion(n-1);  // n! = n(n-1)!

                                         // recursion case

}

 

int fact_iteration(int n)   // factorial iteration

{

    if (n >= 0) {

        int result = 1;

        for(int i=1; i<=n; ++i) {

            result = result * i;

        }

        return result;

    }

    else {

        return numeric_limits::min();

    }

}

 
// 附在这里的是计算Fibonacci数列的dp 的一个优化后的解决方案
// Fibonacci bottom-up dynamic programming.

int fibonacci_dp_bu(int n)

{

    int fib[n];

 

    fib[1] = 1;

    fib[2] = 1;

 

    for (int j=3; j<=n; ++j)

      fib[j] = fib[j-1] + fib[j-2];

 

    return fib[n];

}

 



你可能感兴趣的:(C++,综合)