Java教程

DP动态规划入门(一)

本文主要是介绍DP动态规划入门(一),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

思想:

「分治思想」、「空间换时间」、「最优解」等多种算法思想

动态规划特点:

「分治」是算法中的一种基本思想,其通过将原问题分解为子问题,不断递归地将子问题分解为更小的子问题,并通过组合子问题的解来得到原问题的解。

类似于分治算法,「动态规划」也通过组合子问题的解得到原问题的解。不同的是,适合用动态规划解决的问题具有「重叠子问题」和「最优子结构」两大特性。

重叠子问题

动态规划的子问题是有重叠的,即各个子问题中包含重复的更小子问题。若使用暴力法穷举,求解这些相同子问题会产生大量的重复计算,效率低下。

动态规划在第一次求解某子问题时,会将子问题的解保存;后续遇到重叠子问题时,则直接通过查表获取解,保证每个独立子问题只被计算一次,从而降低算法的时间复杂度。

斐波那契数列(重叠子问题示例)

「暴力递归」→→「记忆化递归」→→「动态规划」
请添加图片描述

int fibonacci(int n) {
    if (n == 0) return 0; // 返回 f(0)
    if (n == 1) return 1; // 返回 f(1)
    return fibonacci(n - 1) + fibonacci(n - 2); // 分解为两个子问题求解
}

请添加图片描述
记忆递归:一个函数初始化数组存储数值,一个函数返回

int fibonacci(int n, vector<int> dp) 
{
    if (n == 0) return 0;           // 返回 f(0)
    if (n == 1) return 1;           // 返回 f(1)
    if (dp[n] != 0) return dp[n];   // 若 f(n) 以前已经计算过,则直接返回记录的解
    dp[n] = fibonacci(n - 1, dp) + fibonacci(n - 2, dp); // 将 f(n) 则记录至 dp
    return dp[n];
}


// 求第 n 个斐波那契数
int fibonacciMemorized(int n) 
{
    vector<int> dp(n + 1, 0); // 用于保存 f(0) 至 f(n) 问题的解
    return fibonacci(n, dp);
}

动态递归**
请添加图片描述
这个就很妙,看起来像是和前面的一样,实则就是利用一个数组来实现状态转移

// 求第 n 个斐波那契数
int fibonacci(int n) {
    if (n == 0) return 0;          // 若求 f(0) 则直接返回 0
    vector<int> dp(n + 1, 0);      // 初始化 dp 列表
    dp[1] = 1;                     // 初始化 f(0), f(1)
    for (int i = 2; i <= n; i++) { // 状态转移求取 f(2), f(3), ..., f(n) 
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];                  // 返回 f(n)
}
/

上述动态规划解法借助了一个 dp 数组保存子问题的解,其空间复杂度为 O(N)

而由于 f(n) 只与 f(n−1) 和 f(n−2) 有关,因此我们可以仅使用两个变量 a , b 交替前进计算即可。此时动态规划的空间复杂度降低至 O(1)

// 求第 n 个斐波那契数
int fibonacci(int n) {
    if (n == 0) return 0;           // 若求 f(0) 则直接返回 0
    int a = 0, b = 1;               // 初始化 f(0), f(1)
    for (int i = 2; i <= n; i++) {  // 状态转移求取 f(2), f(3), ..., f(n) 
        int tmp = a;
        a = b;
        b = tmp + b;
    }
    return b;                       // 返回 f(n)
}

这里第二种方法已经有点失去KISS了,因为他已经把简单的思想给优化了一下利用O(1)空间,可能稍微有点看不懂,自己在纸上画几下就懂啦

「以上内容参考《算法导论》与《算法与数据结构》」

这篇关于DP动态规划入门(一)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!