一、JAVA中队列和栈的实现类
栈:
(1) Stack实现
由于Stack底层是使用Vector的,而Vector支持线程同步,所以整体性能相对较低,如果没有多线程的场景,不建议使用Stack。
(2)LinkedList实现
LinkedList实现了List,Deque(实现了Queue接口)的接口,底层是双向链表实现的,所以不仅可以表示栈,也可以表示队列。
常用API:
stack.push(element); // 压入元素到栈顶
stack.pop(); // 弹出并返回栈顶元素
stack.peek(); // 获取栈顶元素,不弹出
stack.isEmpty(); // 检查栈是否为空
队列:
分为单端队列和双端队列,对应的类是queue和Dequeue,
(1)使用LinkedList实现队列
(2)使用ArrayDeque实现队列(底层实现数组)
(3)使用PriorityQueue实现队列
常用API:
tQueue.add(element); // 添加元素到队尾
Queue.offer(element); // 添加元素到队尾,返回true/false
Queue.poll(); // 移除并返回队首元素
Queue.remove(); // 移除并返回队首元素
Queue.peek(); // 获取队首元素,不移除
Queue.element(); // 获取队首元素,不移除
Queue.isEmpty(); // 检查队列是否为空
二、232.用栈实现队列
题目:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
push
、pop
、peek
、empty
):实现
MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
学习链接:用栈实现队列状态:做出来了
我的思路:定义一个pushStack、popStack,每次模拟队列入队的时候直接把元素放入pushstack,出队的时候,将pushStack的size-1个元素放入popStack,然后出栈pushStack中的最后一个元素,再把popStack的元素放回pushStack。这样很耗时间,代码随想录的思路很好。
代码随想录思路: 也是定义一个pushStack和popStack,入队的时候,将popStack的元素先放回pushStack里面,然后再入队。出队的时候,将pushStack的元素全部放入popStack,然后出队,注意这里可没有放回去,下次如果出队,就直接在这里面出,入队的时候循环上面步骤。这样可以做到很多元素的时候,出队时间几乎O(1)
我的思路:
class MyQueue {
private Stack<Integer> pushStack;
private Stack<Integer> popStack;
private int size;
public MyQueue() {
this.pushStack=new Stack<Integer>();
this.popStack=new Stack<Integer>();
this.size=0;
}
public void push(int x) {
pushStack.push(x);
size++;
}
public int pop() {
while(pushStack.size()>1){
popStack.push(pushStack.pop());
}
int make=pushStack.pop();
while(!popStack.empty()){
pushStack.push(popStack.pop());
}
size--;
return make;
}
public int peek() {
while(pushStack.size()>1){
popStack.push(pushStack.pop());
}
int make=pushStack.peek();
while(!popStack.empty()){
pushStack.push(popStack.pop());
}
return make;
}
public boolean empty() {
if(size==0)return true;
return false;
}
}
代码随想录思路:
三、225. 用队列实现栈
题目:
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(
push
、top
、pop
和empty
)。实现
MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。
学习链接:用队列实现栈状态:做出来了
思路:这道题其实用一个队列就能实现,俩个队列,另一个队列就当备份的作用,其实没有必要,但是题目要求,这里就放俩个队列实现的思路。模拟入栈时,直接入队列。出队列的时候,将size-1个元素放入另一个队列,最后poll最后当前队列最后一个元素,最后直接交换俩个队列,使另一个队列为空(这样就避免循环赋值的时间浪费了)
class MyStack {
private Queue<Integer> pushDeque;
private Queue<Integer> popDeque;
private int size;
public MyStack() {
this.pushDeque=new LinkedList<Integer>();
this.popDeque=new LinkedList<Integer>();
this.size=0;
}
public void push(int x) {
popDeque.offer(x);
while(!pushDeque.isEmpty()){
popDeque.offer(pushDeque.poll());
}
Queue<Integer> queueTemp;
queueTemp=pushDeque;
pushDeque=popDeque;
popDeque=queueTemp;
size++;
}
public int pop() {
size--;
return pushDeque.poll();
}
public int top() {
return pushDeque.peek();
}
public boolean empty() {
if(pushDeque.isEmpty())return true;
return false;
}
}
四、20. 有效的括号
题目:
给定一个只包括
'('
,')'
,'{'
,'}'
,'['
,']'
的字符串s
,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
学习链接:有效的括号状态:做出来了
思路:这道题其实就是直接考了栈的思想,循环遍历这个字符串,然后遇到 (,{,[,就放入栈中,当下一个遇到右括号(也可以是别的右边的)的时候,如果栈里面没有对应的左括号,就证明这个等式错误,直接返回false,这个遍历结束,要注意栈里面要为空才可以返回true.
class Solution {
public boolean isValid(String s) {
Stack<Character> left=new Stack<>();
HashMap<Character, Character> map = new HashMap<Character, Character>() {{
put(')', '(');
put('}', '{');
put(']', '[');
}};
for(int i=0;i<s.length();i++){
char cur=s.charAt(i);
if(cur=='{'||cur=='('||cur=='['){
left.push(cur);
}else{
if(left.size()==0){
return false;
}else{
if(left.pop()!= map.get(cur)){
return false;
}
}
}
}
if(left.size()==0)
return true;
return false;
}
}
四、1047. 删除字符串中的所有相邻重复项
题目:
给出由小写字母组成的字符串
S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca" 输出:"ca"
学习链接:删除字符串中的所有相邻重复项状态:做出来了
思路:这里也可以用栈的思路,由于栈的先进后出可以解决很多问题,栈维护的最终结果,当元素与栈的头元素相等时,头元素出栈,这个元素不放入栈中,当不相等的时候,直接入栈。最后赋值给字符串,再把这个字符串反转就行,当然其实这里可以使用StringBuffer模拟栈,出栈可以使用deleeCharAT,因为每次移除的都是最后一个元素,所以移除的时间复杂度是O(1)。
class Solution {
public String removeDuplicates(String s) {
Stack<Character> make=new Stack<>();
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(make.size()==0){
make.push(c);
}else{
if(make.peek()==c){
make.pop();
}else {
make.push(c);
}
}
}
StringBuffer result=new StringBuffer();
while(!make.empty()) {
result.append(make.pop());
}
return result.reverse().toString();
}
}