描述

给定一个数字三角形,找到从顶部到底部的最小路径和。每一步可以移动到下面一行的相邻数字上。

如果你只用额外空间复杂度O(n)的条件下完成可以获得加分,其中n是数字三角形的总行数。

您在真实的面试中是否遇到过这个题?  是

样例

比如,给出下列数字三角形:

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

从顶到底部的最小路径和为11 ( 2 + 3 + 5 + 1 = 11)。

兄弟们,今天我们就正式进入动态规划的环节了,动态规划很有意思,也很难,今天就简单介绍下思路。

我们在碰到一个题目的时候,首先要思考,这一题要用动态规划吗?

动态规划适用的三个场景:

1、求最大值最小值

2、判断是否可行

3、统计方案个数

动态规划不适用的三个场景:

1、求出所有具体方案而非方案个数

2、输入数据时一个集合(无序),而不是一个序列(有序)。

3、暴力算法的时间复杂度已经是多项式级别。动态规划擅长优化指数级别复杂度(2^n,n!)到多项式级别复杂度(n^2,n^3),不擅长优化从n^3到n^2。

那么动态规划的思路是什么呢?主要分四步:

1、状态 state

灵感,创造力,存储小规模问题的结果

2、方程 function

状态之间的联系,怎么通过小的状态,来算大的状态

3、初始化 initialization

最极限的小状态是什么,起点

4、答案 answer

最大的那个状态是什么,终点

 

OK,说完了动态规划,我们来看这一题。这一题很明显是动态规划每一个条件都符合,当然用dfs也可以做,但是如果用dfs做的话,时间复杂度是2^n。

这一题的思路是如何?对于一个结点来说,它的前序结点一定是它上一行的左边或者右边,要想让到这个结点的路径最小,那么到它的前序结点的路径也一定是最小的。

那么递推式已经出来了:每个结点的最短路径=min(左父结点最短路径,右父节点最短路径)+该结点本身权重

具体看代码,我注释写得很详细了:

class Solution:
    """
    @param triangle: a list of lists of integers
    @return: An integer, minimum path sum
    """
    def minimumTotal(self, triangle):
        # write your code here
        if (len(triangle)==0 or triangle==None):return 0
        dp=[]
        for i in range(len(triangle)):
            temp = []
            for j in range(len(triangle[i])):
                temp.append(0)
            dp.append(temp)
        dp[0][0]=triangle[0][0]
        # dp数组中存的是每个坐标从顶往下的最短路径
        # 每个数字的前一条路,要么从左上来,要么从右上来
        # 左上坐标为row-1,column-1
        # 右上坐标为row-1,column

        # 每行第一列没有左上,只有右上
        for j in range(1,len(triangle)):
            dp[j][0]=dp[j-1][0]+triangle[j][0]
        # 每行最后一列没有右上,只有左上
        for j in range(1,len(triangle)):
            dp[j][-1]=dp[j-1][-1]+triangle[j][-1]

        for i in range(1,len(triangle)):
            for j in range(1,len(triangle[i])-1):
                    # 存最短路径:每个坐标的最短路径=其前序结点的最短路径+该结点本身
                    dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+triangle[i][j]
        #找出最后一行中最小的
        length=len(triangle)-1
        minnum=99999999
        for i in  range(len(dp[length])):
            if(dp[length][i]<minnum):
                minnum=dp[length][i]
        return minnum


s=Solution()
print(s.minimumTotal([
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]))