309. 买卖股票的最佳时机含冷冻期
给定一个整数数组prices
,其中第 prices[i]
表示第 i
天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
集体思路:最主要的就是确定每一个状态,便于推导出状态转移方程
具体完整思路详见注释:
class Solution {
public int maxProfit(int[] prices) {
//动态规划解决
//1,dp数组含义,
//dp[i][j] 第i天的状态为j,所剩余的最多现金为dp[i][j]
//具体状态分析
//dp[0][0]:买入股票的状态,有可能是当天买入,也有可能是买入之后没有卖出
//dp[0][1]:保持卖出股票的状态,就是已经度过了冷冻期,但是没有操作
//dp[0][2]:卖出股票的转态,指的就是当天卖出了股票
//dp[0][3]:今天是冷冻期
int len=prices.length;
if(len==0) return 0;
int[][] dp=new int[len+1][4];
//初始化dp数组,
//根据含义初始化
dp[0][0]=-prices[0];
//其余按照状态初始化为0根据状态转移方程解决
//遍历
for(int i=1;i<len;i++){
//推导每一步的状态转移方程
//1,买入股票可以根据两个状态推导,一个是前一天就是买入的状态
//另一个就是前一天不是买入的状态,那么就有可能是
//前一天是卖出的状态,或者前一天是冷冻期
dp[i][0]=Math.max(dp[i-1][0],
Math.max(dp[i-1][3],dp[i-1][1])-prices[i]);
//2,保持卖出股票的状态,一种是前一天就是这种状态,
//另一种是前一天是冷冻期
dp[i][1]=Math.max(dp[i-1][1],dp[i-1][3]);
//3,当天卖出股票的状态只能是前一天卖出股票
dp[i][2]=dp[i-1][0]+prices[i];
//4,今天是冷冻期,前一天一定是卖出股票的状态
dp[i][3]=dp[i-1][2];
}
//最后结余的最大值一定是在1,2,3状态中诞生,因为买入但不卖出很亏
return Math.max(dp[len-1][1],
Math.max(dp[len-1][2],
dp[len-1][3]));
}
}
给定一个整数数组 prices
,其中 prices[i]
表示第 i
天的股票价格 ;整数 fee
代表了交易股票的手续费用。
你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。
返回获得利润的最大值。
注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
解题思路:相对来说还是比较简单的,使用两种状态就可以解决,一种是买入,一种是卖出,只不过在卖出的时候加上一个手续费用即可,状态转移方程还是根据买与不买的两种状态进行推导,求解出最大值。
具体代码:
class Solution {
public int maxProfit(int[] prices, int fee) {
//动态规划
//1,dp数组含义
//dp[i][0]第i天交易完成之后手中没有股票的最大利润
//dp[i][1]第i天交易完成之后手中有股票的最大利润
int len=prices.length;
int[][] dp=new int[len][2];
//2,确定递推公式
//就是保持前一天的状态不变和改变状态买入或者卖出的最大值
//dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-free)
//dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
//3,初始化
dp[0][0]=0;
dp[0][1]=-prices[0];
//4,循环遍历
for(int i=1;i<len;i++){
dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i]-fee);
dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
}
return Math.max(dp[len-1][0],dp[len-1][1]);
}
}
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]
是数组 [0,3,1,6,2,2,7]
的子序列。
解题思路:可以理解大致的递推公式思路,但是代码实现之后并不是很能理解,之后再看
class Solution {
public int lengthOfLIS(int[] nums) {
//动态规划中的子序列问题
//使用动规五部曲来分析,重点明白dp数组的含义
//1,dp数组含义
//dp[i] 表示以数组下表i之前,以nums[i]结尾的最长递增子序列的长度\
int len=nums.length;
int[] dp=new int[len];
Arrays.fill(dp,1);
int result=0;
//2,确定递推公式
//如果后续元素大于上一个元素,才进行增加
//dp[i]=max(dp[j],dp[j]+1)
//3,dp数组初始化
//根据dp数组含义,每一个do数组值的初始化长度都应该为1
for(int i=0;i<len;i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
dp[i]=Math.max(dp[i],dp[j]+1);
}
}
if(dp[i]>result) result=dp[i];
}
return result;
}
}
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l
和 r
(l < r
)确定,如果对于每个 l <= i < r
,都有 nums[i] < nums[i + 1]
,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]]
就是连续递增子序列。
解题思路:这个就比较简单了,直接秒了,附上代码吧,代码里面甚至都没有注释
class Solution {
public int findLengthOfLCIS(int[] nums) {
int res=1;
int max=1;
for(int i=1;i<nums.length;i++){
if(nums[i]>nums[i-1]){
max++;
}else{
max=1;
}
res=Math.max(max,res);
}
return res;
}
}
剩余的继续补,没办法,谁让我玩嗨了捏!!
By-三条直线围墙