目录
用栈实现队列
题目链接:232. 用栈实现队列
---请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
这里直接给代码 了:
class MyQueue {
Stack<Integer> stack1;
Stack<Integer> stack2;
public MyQueue() {
stack1 = new Stack();
stack2 = new Stack();
}
//直接将元素x压入第一个栈
public void push(int x) {
stack1.push(x);
}
public int pop() {
//注意:待第二个栈为空时,再填充第一个栈的元素进去,不然进出顺序会出问题
if(stack2.isEmpty())
reverse();
return stack2.pop();
}
public int peek() {
//注意:待第二个栈为空时,再填充第一个栈的元素进去
if(stack2.isEmpty())
reverse();
return stack2.peek();
}
public boolean empty() {
return stack1.isEmpty() && stack2.isEmpty();
}
//定义一个方法:将第一个栈的元素全部填充进第二个栈
public void reverse(){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
}
用队列实现栈
题目链接:225. 用队列实现栈
---请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
实现 MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。
思路:
queue1:该队列放的元素跟栈元素放出的顺序一致,例如压入1,2,3三个元素,栈元素:1,2,3;queue1元素:3,2,1。
queue2:辅助队列
push操作时,先让queue2接收,若queue1不为空,则将1队列的元素放入2队列中,此时2队列放的元素跟栈元素放出的顺序一致,最后交换1队列和2队列即可
class MyStack {
Queue<Integer> queue1;
Queue<Integer> queue2;
Queue<Integer> queue;
public MyStack() {
queue1 = new LinkedList();
queue2 = new LinkedList();
}
public void push(int x) {
queue2.offer(x); // 先放在辅助队列中
while (!queue1.isEmpty()){
queue2.offer(queue1.poll());
}
Queue<Integer> queueTemp;
queueTemp = queue1;
queue1 = queue2;
queue2 = queueTemp; // 最后交换queue1和queue2,将元素都放到queue1中
}
public int pop() {
return queue1.poll(); // 因为queue1中的元素和栈中的保持一致,所以这个和下面两个的操作只看queue1即可
}
public int top() {
return queue1.peek();
}
public boolean empty() {
return queue1.isEmpty();
}
}
有效的括号
题目链接:20. 有效的括号
---给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
思路:这里一共有三种不匹配的情况
第一种情况,字符串里左方向的括号多余了 ,所以不匹配。
第二种情况,括号没有多余,但是 括号的类型没有匹配上。
第三种情况,字符串里右方向的括号多余了,所以不匹配。
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。
class Solution {
public boolean isValid(String s) {
Stack<Character> st = new Stack<>();
char[] ch = s.toCharArray();
//这里为方便之后左右括号匹配,遍历到左括号时就将其对应的右括号压进栈
for(int i = 0; i < ch.length; i++){
if(ch[i] == '(')st.push(')');
else if(ch[i] == '[')st.push(']');
else if(ch[i] == '{')st.push('}');
else if(st.isEmpty() || ch[i] != st.peek())//前者栈已经为空,对应第三种情况;后者匹配不对,对应第二种情况
return false;
else
st.pop();//本次循环匹配成功,将栈顶元素压出栈
}
return st.isEmpty();
}
}
删除字符串中的所有相邻重复项
题目链接:1047. 删除字符串中的所有相邻重复项
---给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
思路:创建一个栈空间,然后遍历字符串,将每个字符与栈顶元素比较,若相等,则出栈一个元素,反之则将字符压入栈空间。需要注意的是,当栈为空时不能比较,直接将当前字符压入栈即可。
class Solution {
public String removeDuplicates(String s) {
char[] ch = s.toCharArray();
Stack<Character> stack = new Stack<>();
for(char c : ch){
if(stack.isEmpty())
stack.push(c);
else{
if(c != stack.peek())stack.push(c);
else{
stack.pop();
}
}
}
//字符拼接,用StringBuilder更快!!
StringBuilder sb = new StringBuilder();
while(!stack.isEmpty())sb.append(stack.pop());
return sb.reverse().toString();
}
}