目录
原题链接
剑指offer_在线编程_牛客网 (nowcoder.com)
题目描述
定义一个栈的数据结构,并实现一个能够在常数时间内(O(1))获取栈的最小元素的min
函数。要求在该栈中,调用min
、push
以及pop
的时间复杂度都是O(1)。
题目要求各函数的调用总次数不超过20000次。
解决方案
思路分析
要在O(1)时间复杂度内实现获取栈的最小值,我们需要借助辅助栈来存储当前栈中每个元素入栈时的最小值。辅助栈中的栈顶元素始终是当前主栈中的最小元素。
核心思路
- 主栈(stack):用于存储所有入栈的元素。
- 辅助栈(minStack):用于存储主栈中对应位置的最小值。
流程图解
操作细节
- push操作:将元素压入主栈,同时将该元素与当前辅助栈的栈顶元素(即当前最小值)进行比较。如果该元素小于或等于当前最小值,则也将该元素压入辅助栈。
- pop操作:弹出主栈栈顶元素。如果该元素等于辅助栈的栈顶元素,则同时弹出辅助栈的栈顶元素。
- min操作:直接返回辅助栈的栈顶元素,即当前栈中的最小值。
代码实现
下面是不同语言的代码实现:
Python 语言实现
class MinStack:
def __init__(self):
self.stack = [] # 主栈
self.minStack = [] # 辅助栈,存储最小值
def push(self, val: int) -> None:
self.stack.append(val)
if not self.minStack or val <= self.minStack[-1]:
self.minStack.append(val)
def pop(self) -> None:
if self.stack:
if self.stack[-1] == self.minStack[-1]:
self.minStack.pop()
self.stack.pop()
def top(self) -> int:
if self.stack:
return self.stack[-1]
return -1 # 栈为空时返回-1
def min(self) -> int:
if self.minStack:
return self.minStack[-1]
return -1 # 栈为空时返回-1
C 语言实现
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct StackNode {
int data;
struct StackNode* next;
} StackNode;
typedef struct {
StackNode* top;
StackNode* minTop;
} MinStack;
MinStack* minStackCreate() {
MinStack* stack = (MinStack*)malloc(sizeof(MinStack));
stack->top = NULL;
stack->minTop = NULL;
return stack;
}
void push(MinStack* stack, int val) {
StackNode* node = (StackNode*)malloc(sizeof(StackNode));
node->data = val;
node->next = stack->top;
stack->top = node;
if (stack->minTop == NULL || val <= stack->minTop->data) {
StackNode* minNode = (StackNode*)malloc(sizeof(StackNode));
minNode->data = val;
minNode->next = stack->minTop;
stack->minTop = minNode;
}
}
void pop(MinStack* stack) {
if (stack->top == NULL) return;
if (stack->top->data == stack->minTop->data) {
StackNode* minNode = stack->minTop;
stack->minTop = stack->minTop->next;
free(minNode);
}
StackNode* temp = stack->top;
stack->top = stack->top->next;
free(temp);
}
int top(MinStack* stack) {
return stack->top ? stack->top->data : -1;
}
int min(MinStack* stack) {
return stack->minTop ? stack->minTop->data : -1;
}
void minStackFree(MinStack* stack) {
while (stack->top != NULL) {
StackNode* temp = stack->top;
stack->top = stack->top->next;
free(temp);
}
while (stack->minTop != NULL) {
StackNode* temp = stack->minTop;
stack->minTop = stack->minTop->next;
free(temp);
}
free(stack);
}
Java 语言实现
import java.util.Stack;
class MinStack {
private Stack<Integer> stack;
private Stack<Integer> minStack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int val) {
stack.push(val);
if (minStack.isEmpty() || val <= minStack.peek()) {
minStack.push(val);
}
}
public void pop() {
if (!stack.isEmpty()) {
if (stack.peek().equals(minStack.peek())) {
minStack.pop();
}
stack.pop();
}
}
public int top() {
return stack.isEmpty() ? -1 : stack.peek();
}
public int min() {
return minStack.isEmpty() ? -1 : minStack.peek();
}
}
复杂度分析
- 时间复杂度:
-
push
、pop
、top
、min
操作的时间复杂度均为O(1)。
- 空间复杂度:O(n),其中n为栈中的元素个数。为了支持O(1)的最小值操作,辅助栈可能需要存储与主栈相同数量的元素。
总结
通过使用一个辅助栈,我们可以在O(1)时间复杂度内实现对栈的最小值查询。辅助栈的栈顶始终保持当前栈的最小元素,使得min
操作能够快速返回栈的最小值。