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. border.css(解决移动端1px问题)

    由于某些机型分辨率过高,会导致1px变成2-多px像素的问题,引用bordercss解决 @charset "utf-8"; .border, .border-top, .bord ...

  2. Java中的RSA加解密工具类:RSAUtils

    本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.utils.log.LogUtils; ...

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

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

  4. Hibernate 一对一映射(惟一外键)

  5. git 自己创建了一个项目A,我的同事fork一个B,当我的项目更新的时候,怎么样在他fork的repo上进行相应的更新?

    先把B clone到本地 git clone B_REPOSITORY_URL 再cd到本地B的目录,把A作为一个remote加到本地的B中(一般命名为upstream) git remote add ...

  6. 批量插入Oracle,遇到CLob字段慢的解决办法

    在一次执行批量插入到Oracle表,其他一个字段设置为CLOB,但没有内容,在插入时,在代码指定为CLOB类型,插入相当慢,后来改为VarChar2,速度就上去了,经测试,插入一个65535个字符,没 ...

  7. 深入理解JavaScript系列(39):设计模式之适配器模式

    介绍 适配器模式(Adapter)是将一个类(对象)的接口(方法或属性)转化成客户希望的另外一个接口(方法或属性),适配器模式使得原本由于接口不兼容而不能一起工作的那些类(对象)可以一些工作.速成包装 ...

  8. Centos时间查看修改命令date详解

    1.查看.修改Linux时区与时间 一.linux时区的查看与修改 1,查看当前时区date -R 2,修改设置时区方法1:tzselect 方法2:仅限于RedHat Linux 和 CentOSt ...

  9. Splunk和ELK深度对比

    转自:http://blog.51cto.com/splunkchina/1948105 日志处理两大生态Splunk和ELK深度对比 heijunmasd 0人评论 5312人阅读 2017-07- ...

  10. 清除SQL Server内存

    数据库进行查询时,会缓存结果集,当查询结果过大时会出现内存爆满的情况,如果手动清除SQL所占用的内存呢,在网上搜索一下,把结果贴下面: --强制释放内存 Create procedure [dbo]. ...