目录
第20题:有效的括号
题目描述
代码:
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
//遍历整个字符串,最多只有三对括号
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
//只有这几种情况才可以入栈;
// 不入栈就出栈,为空就说明这个字符串一个都没进去,不可能为真
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else {
if (stack.isEmpty()) {
return false;
}
//出栈情况的具体情况
char topChar = stack.pop();
//比较当前括号和栈顶括号是否匹配,不匹配则错误
if (c == ')' && topChar != '(') {
return false;
}
if (c == ']' && topChar != '[') {
return false;
}
if (c == '}' && topChar != '{') {
return false;
}
}
}
//如果一切顺利则全部进栈之后又出栈,栈必为空
return stack.isEmpty();
}
}
注意:java官方并不建议使用stack类,因为stack类是继承自vector,使用stack会继承vector的方法,同样,即使是官方建议使用的Deque接口,也一样不合适。但此处作为一个做题方式,可以使用。如在面试中遇到质疑此问题的面试官,需要进行解释,或自己实现一个stack类。
第225题:用队列实现栈
题目描述:
思路:
题目要求最多使用两个队列实现,其实只用一个队列就可以实现。栈的操作是从栈顶进入,从栈顶出来,所以用队列实现栈时,栈顶应该是从队头插入,否则出栈无法实现。例如,进栈是1234,出栈是4321,而队列原本的出栈是1234。
代码:
class MyStack {
private Queue<Integer> queue;
/** Initialize your data structure here. */
public MyStack() {
queue = new LinkedList<>();
}
//用队列实现栈时,要从队列的头插入,实现方式就是队列先把原来的依次出,再依次进
/** Push element x onto stack. */
public void push(int x) {
queue.add(x);
//i自己理解下,这里非常重要
for (int i = 1; i < queue.size(); i++) {
queue.add(queue.remove());
}
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
return queue.remove();
}
/** Get the top element. */
public int top() {
return queue.peek();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return queue.isEmpty();
}
}
注意:个人觉得重点不只是对栈,队列的性质的考察,更是对队列方法的考察,建议随手阅读jdk-api文档
第232题:用栈实现队列
题目描述:
思路:
参考队列的原始思路,比较好理解的解法就是以栈1为基,两个栈来回折腾,最终在栈1上实现队列的操作
代码:
class MyQueue {
private Stack<Integer> stack1;
private Stack<Integer> stack2;
/** Initialize your data structure here. */
public MyQueue() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
/** Push element x to the back of queue. */
public void push(int x) {
stack1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
while(!stack1.empty()){
stack2.push(stack1.pop());
}
int res = stack2.pop();
while(!stack2.empty()){
stack1.push(stack2.pop());
}
return res;
}
/** Get the front element. */
public int peek() {
while(!stack1.empty()){
stack2.push(stack1.pop());
}
int res = stack2.peek();
while(!stack2.empty()){
stack1.push(stack2.pop());
}
return res;
}
/** Returns whether the queue is empty. */
public boolean empty() {
return stack1.empty();
}
}
但考虑到还有”进阶“,因此可以直接使用两个栈,共同实现队列。
代码:
class MyQueue {
private Stack<Integer> stack1;
private Stack<Integer> stack2;
//记录栈底
int front;
/**
* Initialize your data structure here.
*/
public MyQueue() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
/**
* Push element x to the back of queue.
*/
public void push(int x) {
//如果栈1为空,则进入的栈1的第一个元素就是栈底,记录。
if (stack1.empty()) {
front = x;
}
//栈顶插入
stack1.push(x);
}
/**
* Removes the element from in front of queue and returns that element.
*/
public int pop() {
//队列要得到队首
//栈2为空时,就把栈1依次出栈,在栈2中依次进栈,栈1为空时,栈底到栈2的栈顶。
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
/**
* Get the front element.
*/
public int peek() {
if(stack2.empty()){
return front;
}
return stack2.peek();
}
/**
* Returns whether the queue is empty.
*/
public boolean empty() {
return stack1.empty() && stack2.empty();
}
}
注意:这个实现在时间复杂度上是全O(1),但空间复杂度,pop为O(n),其他为O(1)
第155题:最小栈
题目描述
代码:
class MinStack {
private Deque<Integer> dataStack;
private Deque<Integer> minStack;
/**
* initialize your data structure here.
*/
public MinStack() {
dataStack = new LinkedList<>();
minStack = new LinkedList<>();
}
//这里是关键,确保每次minStack都会同步添加元素,else里一定要用peek
public void push(int x) {
dataStack.push(x);
if (minStack.isEmpty() || x <= minStack.peek()) {
minStack.push(x);
} else {
minStack.push(minStack.peek());
}
}
public void pop() {
dataStack.pop();
minStack.pop();
}
public int top() {
return dataStack.peek();
}
public int getMin() {
return minStack.peek();
}
}
注意:此题的重点在于理解题意,所谓最小栈,只是求栈中最小值的时间复杂度不为O(n),为O(1),前文中提到正常的栈官方并不建议使用,因此此处采用了官方建议的Deque接口,getMin之外的方法本来就是O(1),因此直接用,注意实现方式。当然此题最好的做法是用自己实现栈的方式来做。