[TOC]
这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
要求
实现一个特殊栈,在实现基本功能之外,再提供返回栈中最小元素的操作。
pop、push、getMin操作时间复杂度均为O(1)。- 设计的栈类可以使用现成的栈结构。
思路
在可以使用现成的栈结构基础上,普通的栈push()、pop()操作时间复杂度均为O(1),但是在获取整个栈的最小元素却需要遍历整个栈,时间复杂度为O(N)。那么难度就在如何将getMin()函数的时间复杂度从O(N)降低到O(1)。
通过空间换时间的思想,建立一个辅助栈来实现:
- 数据栈
stackData:该栈中存放所有元素,保证入栈push()函数、出栈pop()函数、获取栈顶元素top()函数逻辑正常无误。 - 辅助栈
stackMin:该栈中存放栈stackData中所有非严格降序的元素,并且数据栈stackData中最小元素始终保持对应在辅助栈的栈顶元素,即getMin()函数只需返回辅助栈stackMin栈顶元素。
函数设计
push(x)函数:将元素入栈,同时保持辅助栈stackMin元素为非严格降序的。- 将元素入数据栈
stackData。(stackData.push(x)) - 如果辅助栈
stackMin为空,如果待入栈元素小于或等于辅助栈stackMin中最小值,将其压入辅助栈stackMin。(stackMin.push(x))
- 将元素入数据栈
pop()函数:保持数据栈stackData和 辅助栈stackMin数据元素一致。- 将数据栈元素出栈(
stackData.pop()) - 若出栈元素和辅助栈栈顶元素一致,则将辅助栈栈顶元素也出栈(
stackMin.pop())
- 将数据栈元素出栈(
top()返回数据栈栈顶元素。(stackData.peek())getMin()返回辅助栈栈顶元素。(stackMin.peek())
时间复杂度
- 时间复杂度O(1):在执行操作
push()、pop()、top()、getMin()这几个函数时,时间复杂度均为常数级别。 - 时间复杂度O(N):假设有N个元素倒叙入栈时,辅助栈最差情况下回存储N个元素,使用O(N)的额外辅助空间。
stackData:5、4、3、2、1stackMin:5、4、3、2、1
代码
import java.util.Stack;
/**
* <p></p>
*
* @author chencong
* @email ccoder.cc | cong.ccoder@gmail.com
* @date MinStack.java v1.0 2021/8/23 13:41
*/
public class MinStack {
Stack<Integer> stackData, stackMin;
public MinStack() {
this.stackData = new Stack<>();
this.stackMin = new Stack<>();
}
/**
* 入栈
* stackMin为空时,此时待入栈数据便是最小
* stackMin中最小值和待入栈数据比较,如果待入栈数据较小便将其入栈,否则保持不动
*
* @param newNum 待入栈数据
*/
public void push(int newNum) {
if (stackMin.isEmpty() || newNum <= this.getMin()) {
stackMin.push(newNum);
}
this.stackData.push(newNum);
}
/**
* 获取栈顶元素
*
* @return 获取元素
*/
public int top() {
return this.stackData.peek();
}
/**
* 出栈
*
* @return 出栈元素
*/
public int pop() {
int value = this.stackData.pop();
if (value == this.stackMin.peek()) {
this.stackMin.pop();
}
return value;
}
/**
* 获取最小元素
*
* @return 获得数据
*/
public int getMin() {
return this.stackMin.peek();
}
}
单测
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* <p></p>
*
* @author chencong
* @email ccoder.cc | cong.ccoder@gmail.com
* @date MinStackTest.java v1.0 2021/8/23 15:11
*/
public class MinStackTest {
private static MinStack stack;
@Test
public void getMinTest() {
System.out.println(stack.getMin());
Assertions.assertEquals(0, stack.getMin());
}
@BeforeAll
public static void createStackDataTest() {
stack = new MinStack();
stack.push(4);
stack.push(3);
stack.push(1);
stack.push(5);
stack.push(0);
stack.push(2);
}
}
扩展
MinStack中可以扩展实现Comparable,保证除去基本数据类型其余对账均可O(1)获取最小元素。