标签:30 入栈 min 降序 元素 栈顶 pop LeetCode
题目均来自力扣(LeetCode),作者:Krahets。链接:图解算法数据结构
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
inStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.
有了昨天第一题的基础,今天就有头绪多了!
解题思路:栈调用 push() 和 pop() 函数的时间复杂度都是O(1),也就是入栈、出栈直接在栈顶出入即可。难点在于获取栈最小值 min() 函数,如果一个栈硬性获取的话,需要遍历整个栈,时间复杂度为O(N)。可知,需要一个辅助栈。
菜鸡到这就不会了!解析依赖症患者上线,都大四了第一次听到“非严格降序”这个词,解释一下吧。
非严格降序:据百度其实就是“小于等于”的意思,严格降序即小于。
假设有六个元素
5
,
9
,
3
,
4
,
7
,
1
5,9,3,4,7,1
5,9,3,4,7,1的空栈
A
=
[
]
A=[]
A=[]、
B
=
[
]
B=[]
B=[]。栈A用于存储元素,栈B中的元素是栈A的非严格降序元素的子序列。也就是每个入栈A的元素都与栈B的栈顶元素进行对比,如果该元素小于栈B的栈顶元素,则入栈B,否则,只入栈A。
操作:
①栈A、栈B将元素5入栈;
②栈A执行元素9入栈,9比栈B栈顶元素5大,不入栈B;
③栈A执行元素3入栈,3比栈B栈顶元素5小,入栈B;
此时,栈
A
=
[
5
,
9
,
3
]
A=[5,9,3]
A=[5,9,3],栈
B
=
[
5
,
3
]
B=[5,3]
B=[5,3];
④元素4入栈A,4比栈B栈顶元素3大,不入;
⑤元素7入栈A,7比栈B栈顶元素3大,不入;
⑥元素1入栈A,1比栈B栈顶元素3小,入栈B。
最终,栈
A
=
[
5
,
9
,
3
,
4
,
7
,
1
]
A=[5,9,3,4,7,1]
A=[5,9,3,4,7,1],栈
B
=
[
5
,
3
,
1
]
B=[5,3,1]
B=[5,3,1]。
栈A存储了所有元素,而栈B为栈A的非严格降序子序列。
此时,栈B执行出栈即可实现 min() 函数的O(1)复杂度。
函数设计:
push(x) 函数:
1.执行[元素x入栈A];
2.若[栈B为空栈 或 x <= 栈B的栈顶元素],则执行[元素x入栈B];
pop():(保持栈A、B元素的一致性)
1.执行[栈A元素出栈],将出栈元素标记为y;
2.如果[y=栈B的栈顶元素],则执行[栈B元素出栈];
top():返回栈A的栈顶元素;
min():返回栈B的栈顶元素;
选择非严格降序"<="的原因:在栈A具有重复最小值元素时,非严格降序可防止栈B提取弹出最小值元素。
比如说现在有栈
A
=
[
4
,
5
,
3
,
7
,
3
]
A=[4,5,3,7,3]
A=[4,5,3,7,3],那么非严格降序中栈
B
=
[
4
,
3
,
3
]
B=[4,3,3]
B=[4,3,3];当栈A执行 pop() 函数时,元素3弹出,栈
A
=
[
4
,
5
,
3
,
7
]
A=[4,5,3,7]
A=[4,5,3,7],而栈B为栈A的子序列,要保持元素的一致性,栈A弹出元素栈B也要弹出,此时
B
=
[
4
,
3
]
B=[4,3]
B=[4,3],最小元素依然是3。
如果采用严格降序即“<”,那么当重复元素“3”入栈A时,会因为“3不小于3”判断否而不入栈B,此时
B
=
[
4
,
3
]
B=[4,3]
B=[4,3],执行弹出操作后栈
B
=
[
4
]
B=[4]
B=[4],误弹出最小元素。
复杂度分析:
时间复杂度:push(), pop(), top(), min() 四个函数的时间复杂度均为常数级别。
空间复杂度:当共有 N 个待入栈元素时,辅助栈 B 最差情况下存储 N 个元素,使用 O(N) 额外空间。
Java代码
import java.util.Stack;
class MinStack {
Stack<Integer> A, B;
public MinStack() {
A = new Stack<>();
B = new Stack<>();
}
public void push(int x) {
A.add(x);
if(B.empty() || B.peek() >= x)
B.add(x);
}
public void pop() {
if(A.pop().equals(B.peek()))
B.pop();
}
public int top() {
return A.peek();
}
public int min() {
return B.peek();
}
}
最后哔哔:做过一题就有头绪,果然刷题yyds~
标签:30,入栈,min,降序,元素,栈顶,pop,LeetCode 来源: https://blog.csdn.net/weixin_44016035/article/details/120392531
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。