剑指 Offer 30. 包含min函数的栈 / 剑指 Offer 31. 栈的压入弹出序列
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 30. 包含min函数的栈 / 剑指 Offer 31. 栈的压入弹出序列相关的知识,希望对你有一定的参考价值。
剑指 Offer 30. 包含min函数的栈
题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
能使用两个栈和一个栈
使用两个栈就另外使用一个辅助栈来帮助最小值的获取,有两种方法,第一种是每次放入新元素的时候同时更新辅助栈的最小值,另一种方法是只有新元素较小的时候才更新辅助栈,下面是使用第二种方法
class MinStack {
//因为要在O(1)的时间内调用三个方法,因此肯定需要一个辅助的数据结构来实现
//主要是实现min的方法,主要是想每次弹出怎么保证当前辅助栈中的栈顶依然是最小值
//然后就想到了每次压入栈的时候,更新辅助栈的栈顶
//但是我的思维局限在了两个栈中的元素要相同,那样就得调整辅助栈中元素的位置,不好实现
//因此,这里学习了解答的思维,每次压入元素的时候,辅助栈中并不是需要压入同样的数,而是压入对应栈顶高度的最小值就行了
//或者只有小于辅助栈顶的时候选择压入,而大于的时候就不操作,在弹出的时候注意辅助栈顶和数据栈顶相同再弹出
/** initialize your data structure here. */
Stack<Integer> data;
Stack<Integer> helper;
public MinStack() {
data = new Stack<Integer>();
helper = new Stack<Integer>();
}
public void push(int x) {
data.push(x);
if(helper.isEmpty() || (!helper.isEmpty() && helper.peek() >= x)){
helper.push(x);
}
}
public void pop() {
int x = data.pop();
if(helper.peek() == x)
helper.pop();
}
public int top() {
return data.peek();
}
public int min() {
return helper.peek();
}
}
使用一个栈,三种方法,第一种其实和两个栈的第一种方法一样,就是现在用一个数对来存储当前元素和当前最小值,本质上没啥变化
第二种方法是用一个栈存储最小值,最小值更新的时候将新的最小值进行存储
第三种方法存储当前元素与最小值的差值,具体实现上因为是做差,要注意溢出的风险,要用long存储
class MinStack {
Stack<int[]> stack;
//创建一个栈,栈中元素是当前值和当前对应的最小值
/** initialize your data structure here. */
public MinStack() {
stack = new Stack<>();
}
public void push(int x) {
if(stack.isEmpty()){
stack.push(new int[]{x ,x});
}
else{
stack.push(new int[]{x, Math.min(x, stack.peek()[1])});
}
}
public void pop() {
//获得刚加进来的元素
stack.pop();
}
public int top() {
return stack.peek()[0];
}
public int getMin() {
return stack.peek()[1];
}
}
class MinStack {
//又去详细看了一下别的题解,一个栈实现,第一种方法是存放最小值
//在最小值发生改变的时候同时栈中存放当前最小值
/** initialize your data structure here. */
Stack<Integer> stack;
int min = Integer.MAX_VALUE;
public MinStack() {
stack = new Stack<>();
}
public void push(int x) {
//如果比当前最小值小了,就把min入栈
if(x <= min){
stack.push(min);
min = x;
}
stack.push(x);
}
public void pop() {
//如果把当前的最小值弹出了,要更新最小值
if(stack.pop() == min){
min = stack.pop();
}
}
public int top() {
return stack.peek();
}
public int min() {
return min;
}
}
class MinStack {
//又去详细看了一下别的题解,一个栈实现,第二种方法是存储和当前最小值的差值
/** initialize your data structure here. */
Stack<Long> stack;
long min = Long.MAX_VALUE;
public MinStack() {
stack = new Stack<>();
}
public void push(int x) {
if(stack.isEmpty()){
min = x;
stack.push(x - min);
return;
}
stack.push(x - min);
//如果比当前最小值小了,更新min
if(x < min)
min = x;
}
public void pop() {
//如果把当前的最小值弹出了,要更新最小值
if(stack.peek() < 0){
min = min - stack.pop();
}else{
stack.pop();
}
}
public int top() {
if(stack.peek() < 0)
return (int)(min);
return (int)(min + stack.peek());
}
public int min() {
return (int)min;
}
}
剑指 Offer 31. 栈的压入、弹出序列
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
示例 1:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
示例 2:
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zhan-de-ya-ru-dan-chu-xu-lie-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
模拟这个过程,因为要弹出的元素肯定在栈顶,不在栈顶就继续压入,如果把所有元素压入了还是没有找到要弹出的元素就false
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
//我能想到的就是模拟这个过程了
//先判断要弹出的数字是不是在栈顶,有的话直接弹出栈顶,没有的话压入
//如果把所有数字都压入栈中了,仍然找不到当前要弹出的数字,说明这个数字不存在或者说顺序不对
int l = popped.length;
int index = 0; //指向弹出栈的序列下标
//模拟压入过程的栈
Stack<Integer> stack = new Stack<>();
for(int i = 0; i < l; i++){
//如果栈为空或者说栈顶元素和此时要弹出的元素不相等
if(stack.isEmpty() || stack.peek() != popped[index]){
stack.push(pushed[i]);
}
while(!stack.isEmpty() && stack.peek() == popped[index]){
stack.pop();
index++;
}
}
return index == l;
}
}
以上是关于剑指 Offer 30. 包含min函数的栈 / 剑指 Offer 31. 栈的压入弹出序列的主要内容,如果未能解决你的问题,请参考以下文章