这周做了一些关于动态规划的基础题,先总结一些自己的学习心得
青蛙跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
分析:
设青蛙跳上n级台阶共有f(n)种跳法
不难看出,当n>2时,第一次跳台阶时会有两种选择:第一种是第一次跳一级,则第一种的跳法即为剩下的台阶数的跳法f(n-1);第二种是第一次跳两级,则第二种跳法为剩下的n-2级台阶的跳法即f(n-2)。总的f(n)就为两种选择相加。
n=1时,f(1)=1
n=2时,f(2)=f(1)+1
n=3时,f(3)=f(2)+f(1)
n=4时,f(4)=f(3)+f(2)
int numWays(int n) {
int i=1,j=1,result,t=n;
if(n==1||n==0) return 1;
while(t!=1)
{
result=(i+j)%1000000007;
i=j;
j=result;
t--;
}
return result;
}
股票的最大利润
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
分析:
设最大利润为max,设目前为止的最小股票价格为min,设当天的利润为pr[i],
pr[i]=price[i]-min
max=max(pr[i],pr[i-1])
int maxProfit(vector<int>& prices) {
int min,i,profit=0,t;
if(prices.size()<=1) return 0;
min=prices[0];
for(i=0;i<prices.size();i++)
{
if(min>prices[i])
{
min=prices[i];
t=i;
}
if(prices[i]-min>profit)
profit=prices[i]-min;
}
return profit;
}
连续子数组的最大和
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
分析:
要首先清楚的是,子数组的第一个数一定为正数,设add[i]为子数组开始相加一直到当前数的总和,max=max(add[i],add[i-1])
子数组的开始设为原题中的开始,然后相加,若相加后的add为为负数,那么前面的数就可以抛弃了,从当前开始重新相加,最后判断max,add中的较大一方并赋给max即可
int maxSubArray(vector<int>& nums) {
int add=nums[0],max=nums[0],i;
for(i=1;i<nums.size();i++)
{
if(add+nums[i]<nums[i])//表示前面的数的和为负数,放弃这个和,从这个数开始重新相加
add=nums[i];
else
add+=nums[i];
if(max<add)
max=add;
}
return max;
}
礼物的最大价值
在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 12
解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物
分析:
用一个二维数组add[i][j]来表示到达(i,j)时能拿到的礼物的最大值累计量
只有一个元素时,最大值为自己
有一排元素时,最大值为自己的加上自己左边的
有一列时,最大值为自己的加上自己上面的
为多排多列时,最大值为自己的加上上面或左边中的较大一个
int maxValue(vector<vector<int>>& grid) {
int i=0,j=0;
int add[grid.size()][grid[0].size()];
memset(add,0,sizeof(add));//测试用例中含有0,需初始化
for(i=0;i<grid.size();i++)
{
for(j=0;j<grid[0].size();j++)
{
if(i==0&&j==0)
add[i][j]=grid[i][j];
if(i==0&&j>0)
add[i][j]=add[i][j-1]+grid[i][j];
if(j==0&&i>0)
add[i][j]=add[i-1][j]+grid[i][j];
if(i>0&&j>0)
{
if(add[i-1][j]>=add[i][j-1])
add[i][j]=add[i-1][j]+grid[i][j];
if(add[i-1][j]<add[i][j-1])
add[i][j]=add[i][j-1]+grid[i][j];
}
}
}
return add[grid.size()-1][grid[0].size()-1];
}