DP
16. 买卖股票的最佳时期含手续费(medium)
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/submissions/575767896/
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
//分为两种情况
//当天结束手上有股票(前天有股票今天什么都不做或者前天没股票今天购买股票)
//当天结束手上没股票(前天有股票今天卖出股票得到利润支出手续费或者昨天手上没股票今天什么都不做)
int n=prices.size();
vector<int>fdp(n);
vector<int>gdp(n);
fdp[0]=-prices[0];
for(int i=1;i<n;i++)
{
fdp[i]=max(fdp[i-1],gdp[i-1]-prices[i]);
gdp[i]=max(fdp[i-1]+prices[i]-fee,gdp[i-1]);
}
return gdp[n-1];
}
};
17. 买卖股票的最佳时机III(hard)
class Solution {
public:
int maxProfit(vector<int>& prices) {
//分为两种情况
//当天结束手上有股票(前天有股票今天什么都不做或者前天没股票今天购买股票)
//当天结束手上没股票(前天有股票今天卖出股票得到利润交易记录加1或者昨天手上没股票今天什么都不做)
//最多可以完成两笔交易
int n=prices.size();
vector<vector<int>> fdp(n,vector<int>(3,-0x3f3f3f));
vector<vector<int>> gdp(n,vector<int>(3,-0x3f3f3f));
fdp[0][0]=-prices[0];
gdp[0][0]=0;
for(int i=1;i<n;i++)
{
for(int j=0;j<3;j++)
{
fdp[i][j]=max(fdp[i-1][j],gdp[i-1][j]-prices[i]);
gdp[i][j]=gdp[i-1][j];
if(j-1>=0)
gdp[i][j]=max(fdp[i-1][j-1]+prices[i],gdp[i-1][j]);//j-1可能越界,我们特殊处理一下
}
}
return max(gdp[n-1][0],max(gdp[n-1][1],gdp[n-1][2]));
}
};
18. 买卖股票的最佳时机IV(hard)
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/submissions/575774292/
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
//分为两种情况
//当天结束手上有股票(前天有股票今天什么都不做或者前天没股票今天购买股票)
//当天结束手上没股票(前天有股票今天卖出股票得到利润交易记录加1或者昨天手上没股票今天什么都不做)
//最多可以完成k%(n/2)笔交易
//0x3f3f3f,int能表示的最大范围的一半
int n=prices.size();
k=min(k,n/2);//0到k天,一共k+1次交易
vector<vector<int>> fdp(n,vector<int>(k+1,-0x3f3f3f));
vector<vector<int>> gdp(n,vector<int>(k+1,-0x3f3f3f));
fdp[0][0]=-prices[0];
gdp[0][0]=0;
for(int i=1;i<n;i++)
{
for(int j=0;j<k+1;j++) //0到k次
{
fdp[i][j]=max(fdp[i-1][j],gdp[i-1][j]-prices[i]);
gdp[i][j]=gdp[i-1][j];
if(j-1>=0)
gdp[i][j]=max(fdp[i-1][j-1]+prices[i],gdp[i-1][j]);
}
}
int ret=-0x3f3f3f;
for(int l=0;l<k+1;l++)
ret=max(ret,gdp[n-1][l]);
return ret;
}
};
19. 最⼤子数组和(medium)
https://leetcode.cn/problems/maximum-subarray/submissions/575775026/
class Solution {
public:
int maxSubArray(vector<int>& nums) {
//dp表i位置表示以该位置为结尾的子数组的最大值
//子数组分为两种
//长度等于1
//长度大于1
int n=nums.size();
vector<int> dp(n);
dp[0]=nums[0];
int _max=dp[0];
for(int i=1;i<n;i++)
{
dp[i]=max(nums[i],dp[i-1]+nums[i]);
_max=max(_max,dp[i]);
}
return _max;
}
};
20. 环形子数组的最大和(medium)
https://leetcode.cn/problems/maximum-sum-circular-subarray/submissions/575777133/
class Solution {
public:
int maxSubarraySumCircular(vector<int>& nums) {
//环形数组头尾相连
//最大和有两种情况
//一种是子数组在数组中间
//另外一种子数组在数组的两端(正难则反,最大在两端,最小就在中间)
//转化为两个dp表一个求最大和,一个求最小和
int n=nums.size();
vector<int> maxdp(n);
vector<int> mindp(n);
maxdp[0]=nums[0];
mindp[0]=nums[0];
int _max,_min,sum;
sum=_max=_min=nums[0];
for(int i=1;i<n;i++)
{
sum+=nums[i];
maxdp[i]=max(nums[i],maxdp[i-1]+nums[i]);
_max=max(_max,maxdp[i]);
mindp[i]=min(nums[i],mindp[i-1]+nums[i]);
_min=min(_min,mindp[i]);
}
if(sum==_min) //对全是负数的情况-1,-2,-3处理
return _max;
return max(_max,sum-_min);
}
};