leetcode学习记录_单调栈

739. 每日温度

请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
来源:力扣(LeetCode)

思路:单调栈,我们维护一个非递增的栈;

注意:非递增指的是对应下标在目标数组中的值,所以栈里存放的是下标而不是值!

在这里插入图片描述
这里的递减递增其实是相对的,主要还是看栈底和栈顶,题目要求比当前数大的第一个,因为栈先进后出的特性,我们就维护一个栈底到栈顶递减的栈,在遍历数组并且维护栈的时候有
三种情况

当前元素  <   栈顶下标元素     即 T[i]   <   T[st.top()];

当前元素  ==  栈顶下标元素     即 T[i]   ==  T[st.top()];

当前元素  >   栈顶下标元素     即 T[i]   >   T[st.top()];

当T [ i ] <= T[ st.top() ]时,满足我们的非递增的条件,因此可以之间将 i 压入栈中,

而当T [ i ] > T[ st.top() ]时, 就该干活了, 这说明我们找到了比前边元素大的数字,那么就对结果数组赋值,因为栈里都是下标,所以就以栈顶位结果数组的下标进行赋值,值是什么呢?别忘了我们在遍历目标数组,就 for ( int i = 0 ; i < T.size() ; ++i ),i就是当前的下标,而题目要我们求比当前元素大的元素的距离,距离,那用下标来计算,正好就是 i - st.top()

即赋值语句为  T[st.top()] = i - st.top()

然后弹出栈顶
继续对新的栈顶比较,直到不满足条件或者栈为空

上面的步骤完成后,将当前下标入栈
且当次循环结束,继续往下进行目标数组的遍历

代码:

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& T) {
    	int N = T.size();
    	vector<int>res(N);//初始化结果数组
    	stack<int>st;
    	for(int i = 0;i<N;++i)//遍历目标数组
    	{
    		if(st.empty() || T[i] <= T[st.top()])
    		{//满足非递增就入栈
    			st.push(i);
    		}
    		else
    		{//不满足就填入结果数组
    			while(!st.empty() && T[i] > T[st.top()])
    			{
    				res[st.top()] = i - st.top();
    				st.pop();
    			}
    			st.push(i);
    		}
    	}
    	return res;
	}
};


402. 移掉K位数字

定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。
注意:
num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 1 :
输入: num = “1432219”, k = 3
输出: “1219”
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。
来源:力扣(LeetCode)

思路:维护一个单调递增栈,为什么要单调递增?因为同样的数字组成的排列里,递增的排列最小,最小的数字都在高位了,肯定比大的数字在高位要小啊,这就是核心思路

然后这一题有几个得注意的点

一:
维护完单调栈以后,发现k还有剩,为了不浪费,我们要从后面删掉k个数字,比如12345,k = 2,那我们删掉5,4就好了

二:
注意k的次数限制,别删太多了

三:
注意结果的前缀0,虽然目标不会有前缀0,但是我们删掉一部分以后,就有可能会出现前缀0,又因为返回的是字符串,所以我们要删掉可能存在的前缀0,也有可能结果只有前缀0,比如“0000”这也是种特殊情况,需要在返回前判断一下

这题我直接用string的代替栈了,反正也要返回string,直接用string代替栈,还没有中间栈赚差价

class Solution {
public:
    string removeKdigits(string num, int k) {
		string res;
		for(char & ch : num)
		{//这三个条件缺一不可,k保证删除次数不超
			while(k && ch<res.back() && !res.empty())
			{
				res.pop_back();//删除栈顶
				--k;
			}
			rse.push_back(ch);//入栈
		}
		while(k--) res.pop_back();//如果维护单调栈完成,却还能删,就从后面删掉
		int i = 0;
		while(res[i] == '0') ++i;//排除前缀0
		if(i == res.size()) return "0";//如果发现只有0,就返回“0”
		return res.substr(i);//提取没有前缀0的部分并返回
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timathy33

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值