关于各种语言中对队列和栈的介绍,可以参考这个网址中的内容:Hello算法,对于Java语言的集合框架的介绍可以参考这里
232. 用栈实现队列
只使用栈的方法实现队列的方法。这就需要我们对存储在栈内部的数据进行一次倒序排序,可以通过两个栈来实现队列的方法,一个栈保存输入,另一个栈在需要输出的时候,转移数据并输出数据。因此,栈的实例成员如下:
class MyQueue {
ArrayDeque<Integer> input = null;
ArrayDeque<Integer> stack = null;
}
而入队操作则将数据存储在第一个栈中,等到需要出队时再通过pop
方法对数据进行重新排序以满足队列的要求,这时,数据便转移到了另一个栈中,用栈实现队列的pop
方法复杂度为O(n)
。另外,peek()
方法类似,下面一并给出代码:
class MyQueue {
ArrayDeque<Integer> input = null;
ArrayDeque<Integer> stack = null;
public MyQueue() {
this.stack = new ArrayDeque<>();
this.input = new ArrayDeque<>();
}
public void push(int x) {
input.push(x);
}
public int pop() {
if (stack.isEmpty()) {
while (!input.isEmpty())
stack.push(input.pop());
}
return stack.pop();
}
public int peek() {
if (stack.isEmpty()) {
while (!input.isEmpty()) {
stack.push(input.pop());
}
}
return stack.peek();
}
public boolean empty() {
return input.isEmpty() && stack.isEmpty();
}
}
225. 用队列实现栈
这道题与上一道题略有不同,在用栈实现队列时,栈本身的出栈操作就会倒序元素,但是队列的出队操作不会倒序元素,因此我们需要在出队时保留一个元素,然后输出或者查看这个元素。这时,两个队列中,其中一个队列只包含一个元素,用于出栈或者查看,另一个队列保存其他元素。并且每进行一次出栈,都会让两个队列的功能互换,还需要一个flag
用于确定哪个队列用于出栈操作,哪个队列用于保存元素。具体代码如下:
class MyStack {
private ArrayDeque<Integer> temp = null;
private ArrayDeque<Integer> stack = null;
private byte flag;
public MyStack() {
this.temp = new ArrayDeque<>();
this.stack = new ArrayDeque<>();
}
public void push(int x) {
if (flag == 0) temp.offer(x);
else stack.offer(x);
}
public int pop() {
if (flag == 0) {
while (temp.size() > 1) {
stack.offer(temp.poll());
}
flag = 1;
return temp.poll();
}
else {
while (stack.size() > 1) {
temp.offer(stack.poll());
}
flag = 0;
return stack.poll();
}
}
public int top() {
if (flag == 0) {
while (temp.size() > 1) {
stack.offer(temp.poll());
}
return temp.peek();
}
else {
while (stack.size() > 1) {
temp.offer(stack.poll());
}
return stack.peek();
}
}
public boolean empty() {
return temp.isEmpty() && stack.isEmpty();
}
}
20.有效括号
这道题在输入右括号时需要判读上一个元素,在输入完成时,需要判断是否能相互对应,适合使用栈操作。
这里将输入左括号建模为push一个元素,输入右括号建模为pop上一个元素,如果右括号不能与左括号对应则false。
在输入左括号时,根据括号类型的不同,push一个元素,在输入右括号时,根据前一个元素的类别,决定是pop上一个元素,还是返回false。具体代码如下:
class Solution {
public boolean isValid(String s) {
ArrayDeque<Integer> stack = new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
case '(':
stack.push(1);
break;
case '[':
stack.push(2);
break;
case '{':
stack.push(3);
break;
case ')':
if (stack.isEmpty() || stack.pop() != 1) return false;
break;
case ']':
if (stack.isEmpty() || stack.pop() != 2) return false;
break;
case '}':
if (stack.isEmpty() || stack.pop() != 3) return false;
break;
}
}
return stack.isEmpty();
}
}
1047. 删除字符串中所有的相邻重复项
这道题需要删除一个字符串中的重复子串,适合使用栈来解决。栈的结构特点让我们能够能够将当前元素与栈顶元素进行对比,查看是否重复。这道题较为简单,直接给出代码。
class Solution {
public String removeDuplicates(String s) {
ArrayDeque<Character> stack = new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
if (i == 0) stack.push(s.charAt(i));
else {
if (!stack.isEmpty() && stack.peek() == s.charAt(i))
stack.pop();
else stack.push(s.charAt(i));
}
}
char[] res = new char[stack.size()];
for (int i = res.length - 1; i >= 0; i--) {
res[i] = stack.pop();
}
return new String(res);
}
}