84.柱状图中的最大矩形面积
找到左边和右边的较小值,说明以栈顶值为底的时候,不能扩展到这两个位置;
数组头尾都加入0,使能够头尾元素可以作为底来计算。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
//寻找以栈顶元素为底的左右的第一个较小数值,
//单调递减栈
int result = 0;
stack<int> st;
heights.insert(heights.begin(),0);//数组头部插入0
heights.push_back(0);
st.push(0);//将第一个数字推入栈中
//从下标1开始
for(int i=1;i<heights.size();i++){
if(heights[i]>heights[st.top()]){
st.push(i);
}else if(heights[i] == heights[st.top()]){
st.pop();//只记录一个底,可以不加
st.push(i);
}else{
while(!st.empty()&&heights[i]<heights[st.top()]){
int mid = st.top();
st.pop();
if(!st.empty()){
//不为空时,操作;空时直接插入
int left = st.top();
int right = i;
int w=right-left-1;
int h = heights[mid];
result = max(result,w*h);
}
}
st.push(i);
}
}
return result;
}
};
121.买卖股票的最佳时机
1.动态规划
//只有一次买卖操作
//持有股票状态1.当日买入股票2.保持前几天买入股票的状态 (肯定是选取花钱最少的状态)
//卖出股票状态1.当日不卖股票,也就是维持前一天的状态2.当日卖掉股票,更新获得的钱(肯定是选取卖掉股票利润最高的,如果之前的操作不高,那么就更替为今天的卖出状态)
dp[i][0]表示第i天持有股票所得最多现金,
dp[i][1]表示第i天不持有股票最多现金,
class Solution {
public:
int maxProfit(vector<int>& prices) {
//只有一次买卖操作
//持有股票状态1.当日买入股票2.保持前几天买入股票的状态 (肯定是选取花钱最少的状态)
//卖出股票状态1.当日不卖股票,也就是维持前一天的状态2.当日卖掉股票,更新获得的钱(肯定是选取卖掉股票利润最高的,如果之前的操作不高,那么就更替为今天的卖出状态)
//初始化,
int len =prices.size();
/*
vector<vector<int>> dp(len,vector<int>(2));//开辟数组
dp[0][0]-=prices[0];
dp[0][1]=0;
for(int i =1;i<len;i++)
{
dp[i][0] = max(dp[i-1][0],-prices[i]);//买入股票的操作
dp[i][1] = max(dp[i-1][1],prices[i]+dp[i-1][0]);//卖出股票的操作
}
return dp[(len-1)][1];*/
vector<vector<int>> dp(2, vector<int>(2)); // 注意这里只开辟了一个2 * 2大小的二维数组
dp[0][0] -= prices[0];
dp[0][1] = 0;
for (int i = 1; i < len; i++) {
dp[i % 2][0] = max(dp[(i - 1) % 2][0], -prices[i]);
dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);
}
return dp[(len - 1) % 2][1];
}
};
2.贪心算法:取最左最小值,去最有最大值。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int low = INT_MAX;
int result = 0;
for(int i= 0;i<prices.size();i++){
low = min(low,prices[i]);//更新最小值
result = max(result,prices[i]-low);//直接取最大区间利润
}
return result;
}
};
309.最佳买卖股票时期含冷冻期
dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]。
四个状态:
状态一;1.持有股票状态,可以是今天买入,或者是之前就买入了股票后后面没有操作,一直持有。
2.不持有股票状态有两种:
状态三;第一种为今天卖出股票
状态二;第二种为今天不卖出,保持卖出的状态(两天前就卖出了股票,度过了一天的冷冻期;或者前一天就是卖出股票状态,一直没有操作)
状态四;3.今天为冷冻期,但冷冻状态不可持续,只有一天
买入股票状态dp[i][0]:
保持前面的买入状态 dp[i-1][0];
今天买入1.前一天是冷冻期,dp[i-1][3]-prices[i]
2.冷冻期以后的保持卖出状态,dp[i-1][1]-prices[i]
那么dp[i][0] = max(dp[i - 1][0], dp[i - 1][3] - prices[i], dp[i - 1][1] - prices[i]);
保持卖出股票状态dp[i][1]:
状态二+状态四
dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
今天就卖出股票状态dp[i][2]:
昨天一定是持有股票状态:dp[i][2] = dp[i - 1][0] + prices[i];
冷冻期状态dp[i-1][3]:
昨天卖出了股票,dp[i][3] = dp[i - 1][2];
初始化:dp[0][0]=-prices[0];
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==0) return 0;
vector<vector<int>> dp(n,vector<int>(4,0));
dp[0][0]-=prices[0];
for(int i=1;i<n;i++){
dp[i][0] = max(dp[i-1][0], max(dp[i - 1][3] - prices[i], dp[i - 1][1] - prices[i]));
dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
dp[i][2] = dp[i - 1][0] + prices[i];
dp[i][3] = dp[i - 1][2];
}
return max(dp[n - 1][3], max(dp[n - 1][1], dp[n - 1][2]));
}
};
1.两数之和
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//使用map映射 数字和下标
unordered_map<int,int> map;
for(int i=0;i<nums.size();i++){
//遍历当前元素,并且在map中查看是否有匹配的value
auto iter = map.find(target-nums[i]);
//找到说明有匹配值
if(iter!=map.end()){
return {iter->second,i};
}
//没找到则加入当前值及下标
map.insert(pair<int,int>(nums[i],i));
}
return {};
}
};