贪心,分治,回溯,动态规划 4大核心算法思想

4大经典算法问题

如果我们将这四种算法思想分一下类,那贪心、回溯、动态规划可以归为一类,而分治单独可以作为一类,因为它跟其他三个都不大一样。为什么这么说呢?前三个算法解决问题的模型,都可以抽象成我们今天讲的那个多阶段决策最优解模型,而分治算法解决的问题尽管大部分也是最优解问题,但是,大部分都不能抽象成多阶段决策模型

贪心

就是每次取最优,最大解。局部最优,得出全局最优。它是动态规划的一种特例。

实际上,用贪心算法解决问题的思路,并不总能给出最优解,目前使用的比较少,需要针对非常特殊的数据场景。

分治算法(divide and conquer)

分治算法用四个字概括就是“分而治之”,将原问题划分成 n 个规模较小而结构与原问题相似的子问题,递归地解决这些子问题,然后再合并其结果,就得到原问题的解

分治算法是一种处理问题的思想,递归是一种编程技巧

要解决这种数据量大到内存装不下的问题,我们就可以利用分治的思想。我们可以将海量的数据集合根据某种方法,划分为几个小的数据集合,每个小的数据集合单独加载到内存来解决,然后再将小数据集合合并成大数据集合。实际上,利用这种分治的处理思路,不仅仅能克服内存的限制,还能利用多线程或者多机处理,加快处理的速度。

for example

在统计方面比较多,比如统计我国人口,要知道我国人口就要先知道每个省人口,要知道省人口就要知道每个市人口,要知道市人口就要知道每个区县人口,直到村社区,然后汇总求的总人数。

回溯

回溯的处理思想,有点类似枚举搜索。我们枚举所有的解,找到满足期望的解。为了有规律地枚举所有可能的解,避免遗漏和重复,我们把问题求解的过程分为多个阶段。每个阶段,我们都会面对一个岔路口,我们先随意选一条路走,当发现这条路走不通的时候(不符合期望的解),就回退到上一个岔路口,另选一种走法继续走。

常见问题,八皇后和背包的问题。

回溯的问题就是,时间复杂度为O(n^2), 指数级别,复杂度很高。一般使用递归来实现,我们会使用备忘录去记录已经计算过的情况,避免重复计算,有时候我们也可以根据实际情况进行剪枝,加快查询。

动态规划 dynamic programing 又叫 DP

我们把问题分解为多个阶段,每个阶段对应一个决策。我们记录每一个阶段可达的状态集合(去掉重复的),然后通过当前阶段的状态集合,来推导下一个阶段的状态集合,动态地往前推进。

大部分动态规划能解决的问题,都可以通过回溯算法来解决,只不过回溯算法解决起来效率比较低,时间复杂度是指数级的。动态规划算法,在执行效率方面,要高很多。尽管执行效率提高了,但是动态规划的空间复杂度也提高了,所以,很多时候,我们会说,动态规划是一种空间换时间的算法思想。

什么样的问题适合用动态规划来解决呢?换句话说,动态规划能解决的问题有什么规律可循呢?

一般是用动态规划来解决最优问题,而解决问题的过程,需要经历多个决策阶段。每个决策阶段都对应着一组状态。然后我们寻找一组决策序列,经过这组决策序列,能够产生最终期望求解的最优值。

三个特征

1. 最优子结构

最优子结构指的是,问题的最优解包含子问题的最优解。反过来说就是,我们可以通过子问题的最优解,推导出问题的最优解。

我们也可以理解为,后面阶段的状态可以通过前面阶段的状态推导出来。

2. 无后效性

后效性有两层含义,含义是,在推导后面阶段的状态的时候,我们只关心前面阶段的状态值,不关心这个状态是怎么一步一步推导出来的,且当前阶段的状态不受后面阶段的状态影响。

3. 重复子问题

不同的决策序列,到达某个相同的阶段时,可能会产生重复的状态。所以一般可以缓存一起来,避免重复计算。

动态规划DP解法思路

先通过回溯分析出是否存在重复子问题,以及是怎么发生的,然后尝试在纸上画一下,递归树,看是否能用回溯+备忘录的方式解决重复子问题。这样得到的结果与DP最后得到的结果效率差不多。

1. 状态转移表法/ 状态转移方程法

我们先画出一个状态表。状态表一般都是二维的(可能是三维/四维复杂场景),所以你可以把它想象成二维数组。其中,每个状态包含三个变量,行、列、数组值。我们根据决策的先后过程,从前往后,根据递推关系,分阶段填充状态表中的每个状态。最后,我们将这个递推填表的过程,翻译成代码,就是动态规划代码了。

比如:  matrix[i][j] + Math.min(states[i][j-1], states[i-1][j]);

第一个,第二个默认值先找出来。

状态转移方程法有点类似递归的解题思路。我们需要分析,某个问题如何通过子问题来递归求解,也就是所谓的最优子结构。根据最优子结构,写出递归公式,也就是所谓的状态转移方程。有了状态转移方程,代码实现就非常简单了。一般情况下,我们有两种代码实现方法,一种是递归加“备忘录”,另一种是迭代递推。

min_dist(i, j) = w[i][j] + min(min_dist(i, j-1), min_dist(i-1, j))

状态转移方程是解决动态规划的关键

LeetCode 

1. 最小路径和

https://leetcode-cn.com/problems/minimum-path-sum/  采用dp方程

class Solution {
    public int minPathSum(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        int rows = grid.length, columns = grid[0].length;
        int[][] dp = new int[rows][columns];
        dp[0][0] = grid[0][0];
        for (int i = 1; i < rows; i++) {
            dp[i][0] = dp[i - 1][0] + grid[i][0];
        }
        for (int j = 1; j < columns; j++) {
            dp[0][j] = dp[0][j - 1] + grid[0][j];
        }
        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < columns; j++) {
                dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
            }
        }
        return dp[rows - 1][columns - 1];
    }
}

 

 2. 硬币兑换

https://leetcode-cn.com/problems/coin-change/solution/322-ling-qian-dui-huan-by-leetcode-solution/

coins = [1, 2, 5], amount = 11

F(11)=min(F(111),F(112),F(115))+1

3. 乘积最大子数组

https://leetcode-cn.com/problems/maximum-product-subarray/solution/hua-jie-suan-fa-152-cheng-ji-zui-da-zi-xu-lie-by-g/ 

4. 三角形最小路径和

https://leetcode-cn.com/problems/triangle/

[ [2], [3,4], [6,5,7], [4,1,8,3] ]

定义二维 dp 数组「自底向上的递推」。

a. 状态定义:
dp[i][j]表示从点 (i, j) 到底边的最小路径和。

b. 状态转移:
dp[i][j] = min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j]dp[i][j]=min(dp[i+1][j],dp[i+1][j+1])+triangle[i][j]

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();
        // dp[i][j] 表示从点 (i, j) 到底边的最小路径和。
        int[][] dp = new int[n + 1][n + 1];
        // 从三角形的最后一行开始递推。
        for (int i = n - 1; i >= 0; i--) {
            for (int j = 0; j <= i; j++) {
                dp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle.get(i).get(j);
            }
        }
        return dp[0][0];
    }
}

作者:sweetiee
链接:https://leetcode-cn.com/problems/triangle/solution/di-gui-ji-yi-hua-dp-bi-xu-miao-dong-by-sweetiee/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

posted @ 2020-08-27 12:24  lswtianliang  阅读(1529)  评论(0编辑  收藏  举报