1. Triangle

 class Solution {
public:
int minimumTotal(vector<vector<int> > &triangle) {
int n=triangle.size();
int* res=new int[n];
for(int i=;i<n;i++)
res[i]=triangle[n-][i];
for(int i=n-;i>=;i--)
{
for(int j=;j<=i;j++)
{
res[j]=triangle[i][j]+std::min(res[j],res[j+]);
}
}
return res[];
}
};
之前用自顶向下做的,但是用自底向上会更简单些,因为 不用考虑列数是否是第一列或最后一列,行数是否是第一行,等等这一系列问题。而且最后的结果不用再通过遍历一遍最下面一行来找最小值。

2. unique paths

首先是利用了滚动数组的解法:

  class Solution {//滚动数组
public:
int uniquePaths(int m, int n) {
vector<int> dp(n,);
dp[]=;
for(int i=;i<m;i++)
{
for(int j=;j<n;j++)
{
dp[j]=dp[j-]+dp[j];
}
}
return dp[n-];
}
};

然后是普通二维dp数组的解法:

  class Solution {//二维dp数组
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m,vector<int>(n,));
for(int i=;i<m;i++)
dp[i][]=;
for(int i=;i<n;i++)
dp[][i]=;
for(int i=;i<m;i++)
{
for(int j=;j<n;j++)
{
dp[i][j]=dp[i-][j]+dp[i][j-];
}
}
return dp[m-][n-];
}
};

3. unique paths II

首先是使用滚动数组的解法。注意与上一题中的不同。j循环中变为从0开始,因为要确保当obstacleGrid[i][0]为0时,更新dp[j]为0.

 class Solution {//滚动数组
public:
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
if(obstacleGrid.size()==) return ;
int m=obstacleGrid.size(); int n=obstacleGrid[].size();
vector<int> dp(n,);
dp[]=;
for(int i=;i<m;i++)
{
for(int j=;j<n;j++)
{
if(obstacleGrid[i][j]==)
dp[j]=;
else if(j>)//j==0时就不执行了。
dp[j]=dp[j]+dp[j-];
}
}
return dp[n-];
}
};

使用普通二维dp数组。易错点是两层for循环都是从1开始,因为涉及到dp[j-1]。

 class Solution {//普通二维dp数组
public:
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
if(obstacleGrid.size()==) return ;
int m=obstacleGrid.size(); int n=obstacleGrid[].size();
vector<vector<int>> dp(m,vector<int>(n,));
for(int i=;i<m;i++)
{
if(obstacleGrid[i][]==) break;
else dp[i][]=;
}
for(int i=;i<n;i++)
{
if(obstacleGrid[][i]==) break;
else dp[][i]=;
}
for(int i=;i<m;i++)//注意:从1开始
{
for(int j=;j<n;j++)//注意:从1开始
{
if(obstacleGrid[i][j]==) dp[i][j]=;
else
dp[i][j]=dp[i-][j]+dp[i][j-];
}
}
return dp[m-][n-];
}
};

4. minimum path sum

如果不想判断临界条件,可以分配二维dp数组时多分配1行和1列,用dp[i][j]来表示从左上角到grid[i-1][j-1]的最小路径和。

下面的解法是判断临界条件的,未采用上述技巧。

二维dp数组:

 class Solution {
public:
int minPathSum(vector<vector<int> > &grid) {
if(grid.size()==) return ;
int m=grid.size();int n=grid[].size();
vector<vector<int>> dp(m,vector<int>(n,));
dp[][]=grid[][];
for(int i=;i<m;i++)
dp[i][]=dp[i-][]+grid[i][];
for(int i=;i<n;i++)
dp[][i]=dp[][i-]+grid[][i];
for(int i=;i<m;i++)
{
for(int j=;j<n;j++)
{
dp[i][j]=grid[i][j]+std::min(dp[i-][j],dp[i][j-]);
}
}
return dp[m-][n-];
}
};

滚动数组:

 class Solution {
public:
int minPathSum(vector<vector<int> > &grid) {
if(grid.size()==) return ;
int m=grid.size();int n=grid[].size();
vector<int> dp(n,INT_MAX);//初始值需要设成INT_MAX,因为后面有min比较。
dp[]=;
for(int i=;i<m;i++)
{
dp[]+=grid[i][];
for(int j=;j<n;j++)
{
dp[j]=grid[i][j]+std::min(dp[j],dp[j-]);
}
}
return dp[n-];
}
};

5. climbing stairs

 class Solution {
public:
int climbStairs(int n) {
if(n==||n==||n==) return n;
vector<int> dp(n+,);
dp[]=;dp[]=;dp[]=;
for(int i=;i<=n;i++)
{
dp[i]=dp[i-]+dp[i-];
}
return dp[n];
}
};

用熟了之后只用3个变量就可以,不用开辟n个元素的数组。

6. jump game

 class Solution {
public:
bool canJump(int A[], int n) {
int reach=;
for(int i=;i<=reach&&i<n;i++)
{
reach=std::max(reach,A[i]+i);
if(reach>=n-) return true;
}
return false;
}
};

通过变量reach来记录当前能达到的最远位置。

7. jump game II

 class Solution {
public:
int jump(int A[], int n) {
int start=,end=,count=;
int max=;
if(n==) return ;
while(end<n)
{
count++;
for(int i=start;i<=end;i++)
{
if(A[i]+i>=n-) return count;
if(A[i]+i>max)max=A[i]+i; //max表示下一轮while循环时能遍历到的最远的地方
}
start=end+;
end=max;
} }
};

start和end表示每一轮while循环能遍历的元素区域。每下一轮的start都是这一轮的end+1,保证了无缝衔接;每下一轮的end是这一轮中计算出的max,即(在下一轮while循环时)能遍历到的最远的地方。每个元素只被遍历一次,故复杂度为O(n)。最后能覆盖到下标为n-1的元素时所经历的while轮数即为最终答案(最少jump次数)。

想不通时就代入实例跑一下,立马就清晰了。

8. palindrome partitioning II

 class Solution {
public:
int minCut(string s) {
const int n=s.size();
vector<int> f(n+,);
vector<vector<bool>> dp(n,vector<bool>(n,));
for(int i=;i<n+;i++)
{
f[i]=n--i;
}
for(int i=n-;i>=;i--)
{
for(int j=i;j<n;j++)
{
if((i==j)||(s[i]==s[j]&&j==i+)||(s[i]==s[j]&&dp[i+][j-]))//注意判断顺序
{
dp[i][j]=;
f[i]=std::min(f[i],f[j+]+);
}
}
}
return f[];
}
};

9. word break

 class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int n=s.size();
if(n==) return ;
vector<bool> dp(n+,);
dp[]=;
for(int i=;i<=n;i++)//i表示当前长度(从下标0算起)
{
for(int k=;k<i;k++)//k表示左半子串的长度
{//通过k的变化,尝试每种分隔方式
if(dp[k]&&dict.find(s.substr(k,i-k))!=dict.end())//dp[i]表示从下标0开始的长度为i的子串是否满足word break.
{
dp[i]=;
break;
}
}
}
return dp[n];
}
};

可参考以前写的。http://www.cnblogs.com/forcheryl/p/3997304.html

10.  decode ways

 class Solution {
public:
int numDecodings(string s) {
int n=s.size();
if(n==) return ;
vector<int> dp(n+,);
dp[]=;
if(isValid(s.substr(,)))
dp[]=;
for(int i=;i<=n;i++)
{
if(isValid(s.substr(i-,)))
dp[i]+=dp[i-];
if(isValid(s.substr(i-,)))
dp[i]+=dp[i-];
}
return dp[n];
}
private:
int isValid(string s)
{
if(s[]=='') return ;
int tmp=stoi(s);
return tmp>=&&tmp<=;
}
};

关键的是先写出递推式。dp[n]=dp[n-1]*if(condition1)+dp[n-2]*if(condition2)

这里的condition1和condition2分别是判断两个对应的子串(s[i-1]、s[i-2...i-1])是否为valid。为valid时才可以累加上。

注意:dp[n]表示从下标0起的长度为n的子串的decode ways。

http://okckd.github.io/blog/2014/06/24/NineChap-Dynamic-Programming/

http://blog.csdn.net/linhuanmars/article/details/38468361

leetcode Ch2-Dynamic Programming [2014]的更多相关文章

  1. [LeetCode] 139. Word Break_ Medium tag: Dynamic Programming

    Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine ...

  2. [LeetCode] 45. Jump Game II_ Hard tag: Dynamic Programming

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  3. [LeetCode] 55. Jump Game_ Medium tag: Dynamic Programming

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  4. [LeetCode] 63. Unique Paths II_ Medium tag: Dynamic Programming

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  5. [LeetCode] 121. Best Time to Buy and Sell Stock_Easy tag: Dynamic Programming

    Say you have an array for which the ith element is the price of a given stock on day i. If you were ...

  6. [LeetCode] 53. Maximum Subarray_Easy tag: Dynamic Programming

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...

  7. [LeetCode] 312. Burst Balloons_hard tag: 区间Dynamic Programming

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...

  8. [LeetCode] 64. Minimum Path Sum_Medium tag: Dynamic Programming

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  9. [LeetCode] 72. Edit Distance_hard tag: Dynamic Programming

    Given two words word1 and word2, find the minimum number of operations required to convert word1to w ...

  10. [LeetCode] 152. Maximum Product Subarray_Medium tag: Dynamic Programming

    Given an integer array nums, find the contiguous subarray within an array (containing at least one n ...

随机推荐

  1. Git删除和恢复文件

    删除文件: 如果你在本地删除了一个文件但是没有提交到版本库,这时你用 $ git status命令会看到提示: 如果需要从版本库中删除该文件,则需要用 $ git rm 和 $ git commit ...

  2. 初次使用github的艰难尝试。

    序言 github是全英文的网站,初次使用在没有翻译成中文的情况下很容易做出很多无意义或误操作. 当对本地的文件进行修改后,有时候只是想更新到fork下来的自己的仓库里,看看改得效果如何 .有时候是想 ...

  3. ocr 资源

    1. PIL 在图片上添加中文 https://blog.csdn.net/m0_37606112/article/details/78511381 2 .Chinese Text in the Wi ...

  4. 微信公众号中的支付宝支付与微信支付 && 支付宝支付问题(微信bug)

    一般,在微信公众号中的商城都是需要支持微信支付和支付宝支付的,当然,较大的公司对于鹅厂和阿里的站队就不说了,所以这里简单记录一下支付宝支付和微信支付的主要流程.说是简单介绍,这是因为确实不难,因为前端 ...

  5. oracle 层次化查询(生成菜单树等)

    1.简介:Oracle层次化查询是Oracle特有的功能实现,主要用于返回一个数据集,这个数据集存在树的关系(数据集中存在一个Pid记录着当前数据集某一条记录的Id). 2.层次化查询主要包含两个子句 ...

  6. intellij idea NoClassDefFoundError javax.swing.UIManager

    今天启动idea报 NoClassDefFoundError javax.swing.UIManager 可是明明配置好了java 环境 ,后来仔细想了一下只配置了java的bin目录在PATH里 随 ...

  7. 转 WINXP VBOX 给UBUNTU 加共享目录方法

    1. 安装增强功能包(Guest Additions)安装好Ubuntu 9.04后,运行Ubuntu并登录.然后在VirtualBox的菜单里选择"设备(Devices)" -& ...

  8. java获取当前秒数输出

    Date的getSeconds()已经过时了.不建议用.所以用了下面方法 Calendar c = Calendar.getInstance(); while(true) {            c ...

  9. 关于JS闭包

    今天在敲代码的时候,发现很多JQ插件在写闭包的时候都会用到下面的写法: (function ($) { ... })(jQuery); 一时的好奇心驱使,我研究起了这一写法来.大家都知道,在 $ 没有 ...

  10. Truncated incorrect DOUBLE value: 'NO_REFUND'

    解决办法:Mysql中,如果一个字段是字符串,则一定要加单引号 问题原因: `item_refund_state` ) NOT NULL item_refund_state字段的类型是varchar但 ...