动态规划有点难?
动态规划的题目一直挺怕的,一维dp慢慢能做,但是二维dp还是不太会,根据做了的题目,简单总结一下:动态规划的题目终极解法就是:找公式!找公式!找公式!
leetcode53:最大子序和(题目链接https://leetcode-cn.com/problems/maximum-subarray/)
给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
dp[i]表示以第i个数字结尾的子数组的最大和:
d
p
[
i
]
=
{
n
u
m
s
[
i
]
,
i
=
0
或
者
d
p
[
i
−
1
]
<
=
0
d
p
[
i
−
1
]
+
n
u
m
s
[
i
]
,
i
≠
0
并
且
n
u
m
s
[
i
]
>
0
dp[i] = \begin{cases} nums[i],i=0或者dp[i-1]<=0\\ dp[i-1]+nums[i],i≠0并且nums[i]>0 \end{cases}
dp[i]={nums[i],i=0或者dp[i−1]<=0dp[i−1]+nums[i],i̸=0并且nums[i]>0
s[i]
public int maxSubArray(int[] nums) {
if (nums.length==0)
return 0;
int total = nums[0];
int maxSum = nums[0];
for(int i =1;i<nums.length;i++){
if(total>0){
total += nums[i];
}else{
total = nums[i];
}
if(total>maxSum){
maxSum = total;
}
}
return maxSum;
}
leetcode121:买卖股票的最佳时机(题目链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/)
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。(注意你不能在买入股票前卖出股票)
输入:[7,1,5,3,6,4],输出:5
这个题比较容易,找一个dp[length],第i位表示第i天的最大利润,curMin表示前面i天股票的最小价格,
dp[i] = Math.max(prices[i] - curMin,dp[i-1])
public int maxProfit(int[] prices) {
int minprice = prices[0];
int maxprofit = 0;
for (int i = 0; i < prices.length; i++) {
if (prices[i] < minprice)
minprice = prices[i];
else if (prices[i] - minprice > maxprofit)
maxprofit = prices[i] - minprice;
}
return maxprofit;
}
leetcode509:斐波那契(题目链接:https://leetcode-cn.com/problems/fibonacci-number/submissions/)
这个是经典动态规划,公式就是斐波那契数的定义:
f(N) = f(N-1) + F(N-2) ,N>1
public int fib1(int N) {
if (N<2) {
return N;
}
int T1 = 0;
int T2 = 1;
for (int i = 2; i <= N; i++) {
int T3 = T1 + T2 ;
T1 = T2;
T2 = T3;
}
return T2;
}
public int fib2(int N) {
if(N == 0)
return 0;
if(N == 1)
return 1;
return fib(N-1) +fib(N-2);
}
leetcode746:使用最小花费爬楼梯(题目链接:https://leetcode-cn.com/problems/min-cost-climbing-stairs/)
数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i]。每当你爬上一个阶梯你都要花费对应的体力花费值,可以选择继续爬一个阶梯或者爬两个阶梯。需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。
输入:cost = [10,15,20]
输出:15 (从cost[1]走两个阶梯)
输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
输出:6 (从cost[0]开始,cost[2],cost[4],cost[6],cost[7],cost[9])
这个题也是简单的一维动态规划,公式:dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i];
public int minCostClimbingStairs(int[] cost) {
if (cost.length == 0) return 0;
int[] dp = new int[cost.length];
dp[0] = cost[0];
dp[1] = cost[1];
for (int i = 2; i < cost.length; i++) {
dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i];
}
return Math.min(dp[dp.length - 1], dp[dp.length - 2]);
}