语言
Java
232.用栈实现队列
题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
思路
用栈实现队列,想法就是定义两个栈,一个入栈一个出栈,元素放到入栈里,因为栈是先入后出的,再把元push到出栈中,就相当于实现了队列的先进先出。
代码
class MyQueue {
Stack<Integer> stackIn;
Stack<Integer> stackOut;
public MyQueue() {
stackIn = new Stack<>();
stackOut = new Stack<>();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
dumpstackIn();
return stackOut.pop();
}
public int peek() {
dumpstackIn();
return stackOut.peek();
}
public boolean empty() {
return stackIn.isEmpty() && stackOut.isEmpty();
}
private void dumpstackIn() {
if (!stackOut.isEmpty()) return;
while (!stackIn.isEmpty()) {
stackOut.push(stackIn.pop());
}
}
}
易错点
其实这是一道模拟题,基本没有运用的算法。
注意写好各个方法就好了。
时间复杂度
- 时间复杂度: push和empty为O(1), pop和peek为O(n)
- 空间复杂度: O(n)
225. 用队列实现栈
题目
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
思路
用一个队列实现栈,先把栈的元素放到队列中,然后把前size - 1个元素pop到后面,这样顺序就跟栈一样了。
代码
class MyStack {
Deque<Integer> que1;
public MyStack() {
que1 = new ArrayDeque<>();
}
public void push(int x) {
que1.addLast(x);
}
public int pop() {
int size = que1.size();
size--;
while (size-- > 0) {
que1.addLast(que1.peekFirst());
que1.pollFirst();
}
int res = que1.pollFirst();
return res;
}
public int top() {
return que1.peekLast();
}
public boolean empty() {
return que1.isEmpty();
}
易错点
这也是一道模拟的题,思路最重要,注意方法的使用。
时间复杂度
- 时间复杂度: pop为O(n),其他为O(1)
- 空间复杂度: O(n)
20. 有效的括号
题目
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
思路
先遍历字符串如果遇到左括号就将右括号放入栈中、如果遇到左花括号就将右花括号放入栈中、如果遇到左方括号就将右方括号放入栈中,最后如果相同进行消除。有三种情况,第一种字符串没遍历完栈为空了,第二种括号不能匹配,第三种遍历完了栈里还有元素。具体看代码
代码
class Solution {
public boolean isValid(String s) {
Deque<Character> deque = new LinkedList<>();
char ch;
for (int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
if (ch == '(') {
deque.push(')');
} else if (ch == '{') {
deque.push('}');
} else if (ch == '[') {
deque.push(']');
} else if (deque.isEmpty() || deque.peek() != ch) {
return false;
} else {
deque.pop();
}
}
return deque.isEmpty();
}
}
易错点
有很多判断条件千万别落下了,判断栈是否为空,还有元素不匹配的情况,还有最后返回的是栈是否为空。
时间复杂度
- 时间复杂度: O(n)
- 空间复杂度: O(n)
1047. 删除字符串中的所有相邻重复项
题目
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
思路
可以用栈模拟操作进行相邻的就消除,不过本体使用的是字符串,这样就可以直接省去把栈中元素再取出的过程。大体思路就是遇到相同的元素就消除。
代码
class Solution {
public String removeDuplicates(String s) {
StringBuffer res = new StringBuffer();
int top = -1;
for (int i = 0; i <s.length(); i++) {
char c = s.charAt(i);
if (top >= 0 && res.charAt(top) == c) {
res.deleteCharAt(top);
top--;
} else {
res.append(c);
top++;
}
}
return res.toString();
}
}
易错点
注意把top设置成-1;代表字符串的长度。
循环中判断的时候别忘了判断top >= 0
时间复杂度
时间复杂度: O(n)
空间复杂度: O(n)
总结
今天开篇了栈和队列,这几道题主要是思路的模拟。先想好思路还是比较容易地。
明天继续加油,万丈高楼平地起。