【leetcode】120. Triangle

    xiaoxiao2022-06-28  50

    Difficulty:medium

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

    For example, given the following triangle

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

    The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

    Note: Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

    解题思路一(递归时间复杂度为2^n):

    首先考虑使用递归的方法,如果从上至下采用递归的动态规划,那么可以将每一个数字的结果分为两部分:triangle[i][j]+min(triangle[i+1][j],triangle[i+1][j+1].这样就需要求解triangle[i+1][j],和triangle[i+1][j+1]的值,依次类推,当计算到向量的底部时,向上回硕得到了最终的结果。

    但是这样的时间复杂度相对来说较高,因为在自上向下的递归过程中,对于某一个triangle[i][j],都需要进行两次的计算,因为在他的上次层有triangle[i-1][j],和triangle[i-1][j+1]用到这个数字,所以在递归的过程中难免会将同一个数值计算两次,这样导致最终的计算量大幅度上升,时间复杂度达到了O(2^n)。采用递归的方法所需要的额外空间只有n;

    解题思路二(动态规划时间复杂度n*n):

    再考虑使用动态规划自底向上的递推过程,考虑到如果重复计算同一个值会使程序的计算量大幅度上升,所以从下向上,如果需要计算出triangle[i][j],那么下层的triangle[i+1][j]和triangle[i+1][j+1]都已经是已知的了,并且同样的计算triangle[i][j+1]的时候,需要用到triangle[i+1][j+1]和triangle[i+1][j+2],但是计算triangle[i+1][j]时用到的triangle[i+1][j+1]已经在下层计算过不需要重复的计算量,与triangle[i][j]计算过程中用到的triangle[i+1][j+1]的值相同。所以避免了上层用到同一个值时所进行的无谓的计算量。

    因为题目中要求了要最多使用n的额外空间,所以开出一个能容纳每一个位置到底部的最短距离的向量arr[n*(n-1)/2+1],对于每一个位置,通过i,j来计算在arr中的位置,在triangle中triangle[i][j]到底部的最短距离就是arr[(i)*(i-1)/2+j]的值,所以最后需要求的就是arr[0]。

    接下来就是要控制好进行两层循环的界限,以及在动态规划过程中的状态传递方程

    从下到上 for(int i=n-1;i>=0;i--)控制每一层的层数,for(int j=0;j<=i;j++)用来控制在当前层每一个位置的arr[(i)*(i-1)/2+j]的值。

    状态传递方程为arr[(i)*(i-1)/2+j] = triangle[i][j]+min(arr[(i+1)*(i)/2+j],arr[(i+1)*(i)/2+j+1]);

    最终返回arr[0]的值即可。最终的时间复杂度为O(n*n)相对于递归过程如果数据量很大的时候将会有明显的对比。并且额外空间同样为n

    代码如下:

    int min(int a,int b) { if(a<b) return a; else return b; } class Solution { public: int minimumTotal(vector<vector<int>>& triangle) { int n=triangle.size(); int *arr=new int[n*(n-1)/2+1]; for(int i=n-1;i>=0;i--) { for(int j=0;j<=i;j++) { if(i==n-1) arr[(i)*(i-1)/2+j] = triangle[i][j]; else if(i!=n-1) arr[(i)*(i-1)/2+j] = triangle[i][j]+min(arr[(i+1)*(i)/2+j],arr[(i+1)*(i)/2+j+1]); } } int ans=arr[0]; return ans; } };

    转载请注明原文地址: https://ju.6miu.com/read-1124196.html

    最新回复(0)