从二维数组路径最小和看动态规划到维特比算法

博客从二维数组路径最小和问题出发,分析了暴力枚举解法时间复杂度高、贪心算法只能局部最优的问题,进而引出动态规划。阐述了动态规划的关键要点,给出递推式和代码,并分析了时间复杂度,还提及后续将介绍隐马尔科夫模型和维特比算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划/维特比算法----参考 吴军的《数学之美》,七月算法。

 

摘要:主要是从题目--二维数组路径最小和 的暴力枚举解法时间复杂度太高,贪心算法解法只能做到局部最优无法做到全局最优,从而引出动态规划,再到一个特殊但应用广泛的动态规划算法-维特比算法。

 

题目:二维数组路径最小和

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
 

1.暴力求解

m行n列的方格,从左上方走到右下方,每次只能向下或者向右走一步,如果枚举所有的可能路径 ,就是排列问题,要走m+n-2,其中n-1步是向下的,m-1步是向右的,时间复杂是C(m+n-2,n),当m和n非常大的时候,时间复杂度非常高,不适合,枚举不是万能的!

2.贪心算法

贪心算法就是每次在判断是要向右走或者向下走的时候,如果向下的值比较小,就向下走,否则向右走,也就是每次走的时候只判断当前到下一步,哪个比较小,就往哪里走,只能做到局部最优,没办法保证全局最优。

贪心的反例(图1):

1

5

6

2

100

7

100

15

4

14

12

3

13

11

10

这边从第一步出发的时候,有两种选择,向右5,向下2,2小于5,选择向下,但是2后面的只能选择100,而如果选择5,到达右下角的路径可以比100小很多。

 

3.动态规划

图2
1234
5678
9101112
13141516

理解动态规划的几个主要点:

(1)假设我们找到了一条从1到16的最短路径和的路线(路线一),假设它经过15,那么这条路线上的从1到15,必然也是从1到15最短的路径和的路径。假设不是,还能找到路线二可以使1到15更短,那么用路线二替换路线一,就可以找到一条经过15的从1到16的更短路径,这与我们讲的经过路线一的从1到16的路线是最短的路径相违背。

(2)在上面中我们假设已经找到了从1到16的最短路径,但是我们现在是要求从1到16的最短路径,因为从1到达16,肯定要经过12 /15中的一个,我们只要求出从1到12的最短路径和从1到15的最短路径,就可以找到从1到16的最短路径,而要找从1到15的最短路径,我们可以先找到从1到11或者14的最短路径........以此类推,我们要解决问题,可以先求子问题的解,要求子问题的解,我们可以先找到子子问题的解.......以此类推,直到子问题不可再拆解。

(3)从上面的分析我们可以得到递推式:dp[i][j]=Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j],其中当j为0 的时候,dp[i][0]=grid[i][0]+dp[i-1][0],当j为0 的时候,dp[0][j]=grid[0][j]+dp[0][j-1].

输出代码如下:

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

 

时间复杂度分析:因为只要两重循环,所以时间复杂度为O(m*n)

4.隐马尔科夫模型

待续。。。

 

5.维特比算法

待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值