目录
232.用栈实现队列
首先如果用栈和队列互相实现的话,都是用两个。并且栈和队列可以互相转化,所以图的深度优先遍历还是广度优先遍历都是可以使用栈和队列实现的。
然后还有一些细节需要care,在pop的时候就要先将stackIn里面的所有数据都倒进stackOut里面,然后pop数出来。
然后如果分多次进数据的话,就要把stackout里面的数先倒出来,再给其进数据,所以对stackOut有一个判空操作
/**
* 利用两个栈实现队列
*/
class MyQueue {
private Stack<Integer> stackIn;
private Stack<Integer> stackOut;
public MyQueue() {
stackIn = new Stack<>();
stackOut = new Stack<>();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
if (!stackOut.isEmpty()) {
return stackOut.pop();
}
pushIntoOut();
return stackOut.pop();
}
public int peek() {
if (!stackOut.isEmpty()) {
return stackOut.peek();
}
pushIntoOut();
return stackOut.peek();
}
public boolean empty() {
return stackIn.isEmpty() && stackOut.isEmpty();
}
public void pushIntoOut() {
if (stackIn.isEmpty()) {
return;
}
while (!stackIn.isEmpty()) {
stackOut.push(stackIn.pop());
}
}
}
225.用队列实现栈
队列实现栈,依旧可以用两个去实现。但是如何用单向队列去实现栈呢?这也是在营里对我之前观念的一个改善与优化。
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
drainTo(list) 一次性取出队列所有元素
知识点: remove、element、offer 、poll、peek 其实是属于Queue接口。
保持一个队列跟stack出栈顺序相同,故,queue2作为辅助队列,一有元素先放进去,然后将queue1的加在queue2末尾(如果queue1没有元素,则跳过该步骤),将queue1和queue2交换。
利用两个队列来实现栈
/**
* 利用两个队列实现栈
*/
class MyStack {
Queue<Integer> queue1;//queue1保持与stack相同的出栈顺序
Queue<Integer> queue2;
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> temp = new LinkedList<>();
temp = queue1;
queue1 = queue2;
queue2 = temp;
}
public int pop() {
return queue1.poll();
}
public int top() {
return queue1.peek();
}
public boolean empty() {
return queue1.isEmpty();
}
}
Deque 接口继承了 Queue 接口
所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
用一个队列实现栈
用一个队列,就是将queue2这个辅助队列消失,我们不是每次往queue2里面加然后再换了,直接用queue1,push就是普通的push,而pop每次使用的时候,都去弹queue最后的数,所以将这个数前面的数全部从前面挨个加在队列尾。
然后point来到了如果要依次轮换的话,top函数和pop函数的轮换顺序怎么协同。
所以这也是为什么java实现队列可以使用deque的原因
Deque类里面有first和last之分。
/**
* 利用一个队列实现栈
*/
class MyStack {
Deque<Integer> queue;
public MyStack() {
queue = new ArrayDeque<>();
}
public void push(int x) {
queue.offer(x);
}
/**
* 弹出元素的时候,将最末尾的元素弹出,所以把他前面的元素全部按次序加在queue的末尾
*
* @return
*/
public int pop() {
temp();
return queue.pollFirst();
}
public int top() {//返回最末尾的元素
return queue.peekLast();
}
public boolean empty() {
return queue.isEmpty();
}
public void temp() {
int size = queue.size() - 1;
while (size > 0) {
queue.offer(queue.peekFirst());
queue.pollFirst();
size--;
}
}
}
20.有效的括号
使用栈,遇到可以配对的就弹出,如果都放进去了栈不为空的话,返回false。
首先,可以配对这个就有的琢磨,所以需要一个map通过键值对的方式将各种括号存起来。并且左括号去和右括号匹配,压在栈里面就是右括号去找左括号。所以在key和value这个方面要care。
其次,压栈的时候,需要全部压进去,就可以对s里面的字符进行遍历。最后去判断栈是否为空,为空的话就是全部弹出去了。
class Solution {
/**
* 有效字符串需满足:
* 左括号必须用相同类型的右括号闭合。
* 左括号必须以正确的顺序闭合。
* 每个右括号都有一个对应的相同类型的左括号
*
* @param s
* @return
*/
public boolean isValid(String s) {
if (s.length() == 0 || s == null || s.length() % 2 != 0) {
return false;
}
Stack<Character> stack = new Stack<>();
HashMap<Character, Character> hashMap = new HashMap<>();
hashMap.put(']', '[');
hashMap.put('}', '{');
hashMap.put(')', '(');
stack.push(s.charAt(0));
for (int i = 1; i < s.length(); i++) {
if (!stack.isEmpty() && stack.peek().equals(hashMap.get(s.charAt(i)))) {
stack.pop();
continue;
}
stack.push(s.charAt(i));
}
return stack.isEmpty();
}
}
1047.删除字符串中的所有相邻重复项
个人看到题目之后的反应----->无非就是个重复循环,但是细想之后,如果是循环的话这个循环的跳出条件是什么?单看一趟去重的话是很容易的。那么怎么判断之后字符串里面没有重复如何跳出呢?在一趟去比较之后再有相邻的还是直接move的话,所以感觉循环就是走一遍s。走完s返回stack逆序。
stack要逆序的话这边就可以使用deque。利用first和last来判断
class Solution {
/**
* 删除字符串里面的重复项
*
* @param s
* @return
*/
public String removeDuplicates(String s) {
Deque<Character> stack = new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
if (!stack.isEmpty() && stack.peekLast().equals(s.charAt(i))) {
stack.pollLast();
continue;
}
stack.addLast(s.charAt(i));
}
char[] ch = new char[stack.size()];
int i = 0;
while (!stack.isEmpty()) {
ch[i++] = stack.peekFirst();
stack.pollFirst();
}
return new String(ch);
}
}
掌握deque,以及栈和队列的相互转换方法
2022.10.10补