leetcode120题

关键词:动态规划,重叠子问题,原地修改,空间压缩,vector函数,std::

题解

解法1(自顶向下):

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
    vector<vector<int>> path(triangle);//开辟同形状的路径三角形,值为当前位置的最小路径值
    int row=triangle.size();    
    path[0][0]=triangle[0][0];
    for(int i=1;i<row;i++){
        for(int j=0;j<=i;j++){
            if(j==0)
                path[i][j] = path[i-1][j] + triangle[i][j]; 
            if(j>0 && j<i)
                path[i][j] = min(path[i-1][j], 
                path[i-1][j-1])+triangle[i][j];
            if(j==i)
                    path[i][j] = path[i-1][j-1]+triangle[i][j];
        }
    }
    return *std::min_element(path[row-1].begin(),path[row-1].end());
    }

};
class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
    //改进版,没有必要在开辟一个二维数组,直接修改triangle(原地修改)*
    int row=triangle.size();    
    for(int i=1;i<row;i++){
        triangle[i][0]+=triangle[i-1][0];
        triangle[i][i]+=triangle[i-1][i-1];
        for(int j=1;j<i;j++)
            triangle[i][j] = min(triangle[i-1][j], triangle[i-1][j-1])+triangle[i][j];
    }
    return *std::min_element(triangle[row-1].begin(),triangle[row-1].end());
    }
};

解法2(自底向上):

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
    //自底向上的解法,避免了临界值的讨论
    //采用空间压缩(减少对二维数组的访问,变为对一维数组的访问)
    int row=triangle.size();    
    vector<int> res=vector<int>(triangle[row-1]);//一维数组
    for(int i=row-2;i>=0;i--)
        for(int j=0;j<=i;j++)
            res[j]=min(res[j],res[j+1])+triangle[i][j];
    return res[0];
    }
};

解法3(暴力破解):
待补
解法4(递归):
待补

注:
1.暴力破解的问题是重复的路径计算了多次,但无需开辟空间存储路径值。
2.动态规划法避免了重复计算,并且存储值的方法有:
  a.额外开辟空间(记忆化搜索)
  b.原地修改(即在提给数组上进行修改,本质是覆盖)
  c.空间压缩(粗浅的理解:二维数组通过覆盖的方法化为一维数组,实现空间的节约及访问的便捷。)
3.动态规划关键:
  拆分问题,保存子问题答案,状态转移方程
  问题形式:具有重叠子问题最优子结构
4.自底向上自顶向下 时间性能差不多,不同:a.代码结构(简洁性),b.可能避免掉约束条件
5.分治法:子问题相互独立。 动态规划:子问题有关联
6.其他:
   最优化原理:最优化策略的子策略总是最优的
   无后效性:每个状态都是对过去历史的一个完整总结
   空间换时间 ->避免重复计算产生的冗余 ->将指数级时间转为多项式时间 (参考:百度百科-动态规划)
7.题解一中的两种解法,关于边界情况的处理,注意累加(也是一种覆盖)的使用,可使得代码更简洁。

语法

1.vector:
 a.vector< int > var1;
  var1=vector< int >(length,value); 先定义,再赋值。
  vector< int > var1(length,value);赋值定义同时完成
 b.vector< int > var2 (var1). 和var1同值同结构
 c.vector< int > var3( length ).指定长度,值默认
 d.vector< vector< int > > var4(5).指定5行(vector甚至允许每行的长度不一样,即可以构造非矩阵形式的二维数组) var4 等价于var4(0)的写法,即0行。
  另:<vector < int >‘空格 ’> 否则会和 >>输入符冲突
   vector<vector < int > > var=vector<vector < int >>(行数,vector< int >(列数,值))
 e.var4.push_back(var3) 末尾添加一行,var4此时6行
 f.var4[0].size(); 第一行的长度
 g.与普通数组的比较:
   1能够一次性批量赋同一个值,而对于int dp[5][5]={1};只是给dp[0][0]赋值为1,其余值默认为0;
   2.int dp[N][M]这种写法是错误的,只能放常量,vector则支持变量。

2.*std::max/min_element( arr.begin() , arr.end())

3.关于std::
 a.名字空间std定义了C++标准库中的函数和对象
 b.被std限定后的标识符作用范围就变成了全局域
  #include< iostream >
  std::cout<<value;
等价于
  #include< iostream >
  using namespace std;//将标准库中的全部暴露在全局域中
  cout<<value;
等价于
  #include< iostream.h > (非标准库)
  cout<<value;
 c.#include “iostream"与#include< iostream >的区别:前者先在当前目录找iostream文件,找不到再去系统头文件路径找,后者反之。因此,做为一个良好的习惯,在包含系统头文件时尽量用<>,而在包含自己的工程中的头文件时用”"。
 e.参考链接:
 https://www.cnblogs.com/mhq-martin/p/8604842.html
 https://zhidao.baidu.com/question/431965787776866044.html

其他

1.leetcode 同样的代码每次执行结果也会不同。
2.12ms 8ms 4ms 没有区别,可能下次执行时间就是一样的值了,除非出现100ms以上的差别,否则视为等同。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值