【leetcode】120. Triangle

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;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值