文章目录
题目
232. 用栈实现队列
[请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
- void push(int x) 将元素 x 推到队列的末尾
- int pop() 从队列的开头移除并返回元素
- int peek() 返回队列开头的元素
- boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。](https://leetcode.cn/problems/implement-queue-using-stacks/)
此题自己琢磨了1个小时,差不多能做出来,大体思路就是:
- push方法:直接就往st1里放数就好了
- pop方法:
如果st2里面有元素,就弹出
如果没有,然后将st1所有元素弹出,并放入st2中,然后弹出 - peak方法:
就是利用上述的pop方法弹出,并记录数值,然后将数值再输入到st2上,返回x即可 - empty方法:
就是判断st1和st2都为空,则返回true,否则返回false
class MyQueue {
Stack<Integer> st1;
Stack<Integer> st2;
public MyQueue() {
st1 = new Stack<Integer>();
st2 = new Stack<Integer>();
}
public void push(int x) {
st1.push(x);
}
public int pop() {
if(!st2.isEmpty()){
return st2.pop();
}
while(!st1.isEmpty()){
st2.push(st1.pop());
}
return st2.pop();
}
public int peek() {
int x = this.pop();
st2.push(x);
return x;
}
public boolean empty() {
if(st1.isEmpty()&&st2.isEmpty()){
return true;
}
return false;
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
学习:一定要懂得复用,功能相近的函数要抽象出来,不要大量的复制粘贴,很容易出问题!
在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以
不进行数据的全部导入,会导致不进行先进先出,若st1多个元素,导致st1栈的元素,顺序错乱
peak方法:然先用pop方法弹出,并记录为x,然后再push进去,返回x,此方法挺精彩,以前没见过
225. 用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
- void push(int x) 将元素 x 压入栈顶。
- int pop() 移除并返回栈顶元素。
- int top() 返回栈顶元素。
- boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
注意:
你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可
此题虽然没做过,但是由于上一题与此类似,基本上画个图,研究研究也能做出来,大约30分钟做左右,大体思路是:
- push方法:直接放进队列就好了
- pop方法,把1个元素放到队列1,其他元素放到队列2,然后把队列1与队列2进行调换,弹出队列2即可
- empty方法,和上题是一样的,若两队列皆为空,则返回true,否则则返回false
- top方法可以用上题方法类似的做法,先把元素退出队列,然后赋值,然后把元素再放回去
遇到的问题是:队列要实现的是Queue接口,而不是List接口,或者是其他的类,否则会导致很多方法无法调用
队列1与队列2进行交换需要新建一个队列,与字符串做交换是类似的
class MyStack {
Queue<Integer> li1; // Queue而不是list
Queue<Integer> li2;
public MyStack() {
li1 = new LinkedList<Integer>();
li2 = new LinkedList<Integer>();
}
public void push(int x) {
li1.add(x);
}
public int pop() {
while(li1.size()!=1){
li2.add(li1.poll());
}
Queue<Integer> temp = new LinkedList<Integer>();
temp = li1;
li1 = li2;
li2 = temp;
return li2.poll();
}
public int top() {
int x = this.pop();
li1.add(x);
return x;
}
public boolean empty() {
if(li1.isEmpty()&&li2.isEmpty()){
return true;
}
return false;
}
}
学习:
两个队列实现栈:第二个队列实际上只是有备份的作用
第一队列实现栈:一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。
class MyStack {
// Deque 接口继承了 Queue 接口
// 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
Deque<Integer> que1;
/** Initialize your data structure here. */
public MyStack() {
que1 = new ArrayDeque<>();
}
/** Push element x onto stack. */
public void push(int x) {
que1.addLast(x);
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
int size = que1.size();
size--;
// 将 que1 导入 que2 ,但留下最后一个值
while (size-- > 0) {
que1.addLast(que1.peekFirst());
que1.pollFirst();
}
int res = que1.pollFirst();
return res;
}
/** Get the top element. */
public int top() {
return que1.peekLast();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return que1.isEmpty();
}
}
20. 有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
此题看了十分钟,没有思路去做,应该思路比较简单才对~~~~
class Solution {
public boolean isValid(String s) {
Stack<Character> st = new Stack<>();
char ch;
for(int i=0;i<s.length();i++){
ch=s.charAt(i);
// 碰到左括号,就把相应的右括号入栈
if(ch=='('){
st.push(')');
}else if(ch=='{'){
st.push('}');
}else if(ch == '['){
st.push(']');
}else if(st.isEmpty()||st.peek()!=ch){ // 1 2
return false;
}else{// 如果是右括号判断是和栈顶元素匹配
st.pop();
}
}
return st.isEmpty(); // 最后判断栈中元素是否匹配 // 3
}
}
学习:
括号匹配是使用栈解决的经典为题
linux系统 cd命令也有用到栈
括号不匹配的三种情况?
此题实际上还是挺难的,需要考虑完三种不对的情况,然后如果匹配的话,还要对应栈中元素的弹出
1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
此题和上一题差不多,差不多20分钟就做出来了,主要的思路就是:
先判空,然后如果栈中无元素或者元素不等于栈顶元素,则将元素放进栈中否则,则将弹出一个栈顶的元素
最后结束后,将栈中的元素弹出,加到sb中,对sb反转,然后转为String,并返回
碰到最大的问题是怎样才能把栈中的元素弹出并转为字符串,并且不会顺序错误,并且不会出现数组
解决方式就是转为sb,然后反转,最后转为String
class Solution {
public String removeDuplicates(String s) {
if(s.length()==0&&s==null) return null;
Stack<Character> st = new Stack<Character>();
char ch;
for(int i=0;i<s.length();i++){
ch = s.charAt(i);
if(st.empty()||st.peek()!=ch){
st.push(ch);
}else{
st.pop();
}
}
StringBuilder sb = new StringBuilder();
while(!st.empty()){
sb.append(st.pop());
}
return sb.reverse().toString();
}
}