栈和队列
第一题 括号匹配问题。
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses
例一
输入:s = “()”
输出:true
例二
输入:s = “()[]{}”
输出:true
例三
输入:s = “(]”
输出:false
这道理我们可以使用栈,为什么呢,栈是采用先进后出的,类似于弹夹一样。我们先让一个括号进去,然后让这个括号和下一个括号,如果这俩组成一个闭合,那么我们就移除栈中的元素放第三个。
我们要分三种基本情况
第一大种类就是对应
第一就是刚好两两对应
如"()","{[]}";我们让他们对应只要循环走完栈就好了。
第二是左边多左边多的花会导致循环走完栈还有元素,我们直接返回false就好。
第三是右边比较多,当字符串遍历到左括号的时候发现栈为空。
第二种为空
直接false。
第三种根本不匹配。
走完栈还有直接false。
class Solution {
public boolean isValid(String s) {
if(s==null)
{
return false;
}
if(s.length()==0){
return true;
}
Stack<Character>stack=new Stack<>();
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
if(ch=='{'||ch=='('||ch=='['){
stack.push(ch);
}else{
if(stack.empty()){
System.out.println("右括号多");
return false;
}
char tmp=stack.peek();
if(tmp=='('&&ch==')'||tmp=='{'&&ch=='}'||tmp=='['&&ch==']'){
stack.pop();
}else{
System.out.println("左右括号不一致");
return false;
}
}
}
if(!stack.empty()){
System.out.println("左括多");
return false;
}
return true;
}
}
第二题队列实现栈。
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-stack-using-queues
**思考:**我们知道栈是先进后出而队列是先进先出,因此我们可以弄两个队列实现栈,比如我们栈里面有1,2,3顺序放入,我们要拿出3可以把12放到另外一个空队列,那么只有一个数的队列就是要出的元素
class MyStack {
public MyStack() {
}
public void push(int x) {
}
public int pop() {
}
public int top() {
}
public boolean empty() {
}
}
以上是要我们实现的方法
public boolean empty()这个比较简单只要返回两个列表都为空即可
public void push(int x) 这个方法就是看哪个是空队列。
public int pop() 这个要判断是否为空,然后
class MyStack {
private Queue<Integer> qu1=new LinkedList<>();
private Queue<Integer> qu2=new LinkedList<>();
public MyStack() {}
public void push(int x) {
if(!qu1.isEmpty()){
qu1.offer(x);
}else if(!qu1.isEmpty()){
qu2.offer(x);
}else{
qu1.offer(x);
}
}
public int pop() {
if(empty()){
return -1;
}
int e=-1;
if(!qu1.isEmpty()){
int size=qu1.size();
for(int i=0;i<size-1;i++){
e=qu1.poll();
qu2.offer(e);
}
e=qu1.poll();
}else{
int size=qu2.size();
for(int i=0;i<size-1;i++){
e=qu2.poll();
qu1.offer(e);
}
e=qu2.poll();
}
return e;
}
public int top() {
if(empty()){
return -1;
}
int e=-1;
if(!qu1.isEmpty()){
int size=qu1.size();
for(int i=0;i<size;i++){
e=qu1.poll();
qu2.offer(e);
}
}else{
int size=qu2.size();
for(int i=0;i<size;i++){
e=qu2.poll();
qu1.offer(e);
}
}
return e;
}
public boolean empty() {
return qu1.isEmpty()&&qu2.isEmpty();
}
}
第三题用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-queue-using-stacks
思考我们还是采用上面的方法搞俩栈。一个放1,2,3.然后把3.21.取到第二个队列然后取出第二个队列的头
模板
class MyQueue {
public MyQueue() {
}
public void push(int x) {
}
public int pop() {
}
public int peek() {
}
public boolean empty() {
}
}
做法
class MyQueue {
private Stack<Integer> sk1;
private Stack<Integer> sk2;
public MyQueue() {
sk1=new Stack<>();
sk2=new Stack<>();
}
public void push(int x) {
sk1.push(x);
}
public int pop() {
if(empty()){
return -1;
}
if(sk2.empty()){
while(!sk1.empty()){
sk2.push(sk1.pop());
}
}
return sk2.pop();
}
public int peek() {
if(empty()){
return -1;
}
if(sk2.empty()){
while(!sk1.empty()){
sk2.push(sk1.pop());
}
}
return sk2.peek();
}
public boolean empty() {
return sk1.empty()&&sk2.empty();
}
}
第四题 实现一个最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack
输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
这个题我们的最小值在发生改变!我们用两个栈一个正常栈一个最小值栈,这样我们pop的时候就简单多了,判断一下等不等就完事了。
class MinStack {
private Stack<Integer> stack=new Stack<>();
private Stack<Integer> minstack=new Stack<>();
public MinStack() {
}
public void push(int val) {
stack.push(val);
if(minstack.empty()){
minstack.push(val);
}else{
if(val<=minstack.peek()){
minstack.push(val);
}
}
}
public void pop() {
int x=stack.pop();
if(x==minstack.peek()){
minstack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return minstack.peek();
}
}
第五题设计循环队列
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/design-circular-queue
MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
circularQueue.enQueue(1); // 返回 true
circularQueue.enQueue(2); // 返回 true
circularQueue.enQueue(3); // 返回 true
circularQueue.enQueue(4); // 返回 false,队列已满
circularQueue.Rear(); // 返回 3
circularQueue.isFull(); // 返回 true
circularQueue.deQueue(); // 返回 true
circularQueue.enQueue(4); // 返回 true
circularQueue.Rear(); // 返回 4
题解
我们可以用环形的队列去理解。我们空出来一个。这样当前后相遇的话一定为空。
我们如果想从7走到0下标可以使用加1然后%本身。就可以。
下面是具体代码实现
class MyCircularQueue {
private int[] elem;
private int usedSize;
private int front;
private int rear;
public MyCircularQueue(int k) {
this.elem=new int[k+1];
}
public boolean enQueue(int value) {
if(isFull()){
return false;
}
this.elem[this.rear]=value;
this.rear=(this.rear+1)%this.elem.length;
return true;
}
public boolean deQueue() {
if(isEmpty()){
return false;
}
this.front=(this.front+1)%this.elem.length;
return true;
}
public int Front() {
if(isEmpty()){
return -1;
}
int val=this.elem[front];
return val;
}
public int Rear() {
if(isEmpty()){
return -1;
}
if(this.rear==0){
return this.elem[this.elem.length-1];
}
return this.elem[this.rear-1];
}
public boolean isEmpty() {
if(this.front==this.rear){
return true;
}else{
return false;
}
}
public boolean isFull() {
if((this.rear+1)%this.elem.length==this.front){
return true;
}else{
return false;
}
}
}