oj链接
设计一个支持 push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
大体思路:
在栈中要找到最小元素我们可以借助两个栈,一个是普通栈(stack),另一个是存储最小值的栈(minStack),我们每放一个值在栈中如果是栈中最小的,我们就去记录这个值然后放入minStack栈中,相同元素也要放入栈中,元素弹出的时候要两个栈里面的相同元素也要弹出,最后可以获得栈顶元素,并检索栈中的最小元素。
核心代码:
public void push(int val) {
stack.push(val);
if(minStack.empty()) {
minStack.push(val);
} else {
int x = minStack.peek();
if (val <= x) { // = 必须加,不加出bug
minStack.push(val);
}
}
}
public void pop() {
int x = stack.pop();
if(x == minStack.peek()) {
minStack.pop();
}
}
class MinStack {
private Stack<Integer> stack;
private Stack<Integer> minStack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int val) {
stack.push(val);
if(minStack.empty()) {
minStack.push(val);
} else {
int x = minStack.peek();
if (val <= x) { //= 必须加
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();
}
}
oj 链接
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
大体思路:
我们需要建立一个栈,然后遍历字符串,把左边所有的括号全放进栈里面,遍历的右边的括号的时候,
1、如果遍历到的括号与栈里面的括号对应,那么弹出栈,并且栈和字符串都遍历完,返回true;
2、如果左括号多,当字符串遍历完成的时候,那么栈是不空的,返回false。
3、如果右括号多:当字符串遍历到右括号的时候,此时去栈内找左括号,发现栈是空,返回false。
完成代码:
class Solution {
public boolean isValid(String s) {
if(s.length() == 0) return true;
if(s == null) return false;
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 类:
OJ链接
大体思路:
用队列实现栈,首先必须需要两个队列,如果两个队列都为空,放元素就先放到qu1里面,之后还要添加元素那么就是往队列不为空的队列里面放元素。那么你要弹出一个后入先出的一个栈元素,就要把这个队列里面size-1个元素放入另一个队列中,最后一个元素弹出即可,之后循环反复。
核心代码:
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;//返回e实现一个后入先出的栈
}
class MyStack {
private Queue<Integer> qu1;
private Queue<Integer> qu2;
public MyStack() {
qu1=new LinkedList<>();
qu2=new LinkedList<>();
}
public void push(int x) {
if(!qu1.isEmpty()){
qu1.offer(x);
}else if(!qu2.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 类:
OJ链接
大体思路:
用栈实现队列,首先必须需要两个栈,队列是先进先出,所有我们用一个栈放入数据,从这个栈里面弹出再放入另一个栈,最后从另一个栈弹出就是实现队列,中途如果要加元素,也是先放入第一个栈里面,然后另一个栈弹出完后再放入另一个栈然后弹出。
核心代码:
public int pop() {
if(empty()) return -1;
if(s2.empty()) {
while(!s1.empty()) {
s2.push(s1.pop());
}
}
return s2.pop();
}
class MyQueue {
private Stack<Integer> s1;
private Stack<Integer> s2;
public MyQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
public void push(int x) {
s1.push(x);//指定放在s1;
}
public int pop() {
if(empty()) return -1;
if(s2.empty()) {
while(!s1.empty()) {
s2.push(s1.pop());
}
}
return s2.pop();
}
public int peek() {
if(empty()) return -1;
if(s2.empty()) {
while(!s1.empty()) {
s2.push(s1.pop());
}
}
return s2.peek();
}
public boolean empty() {
return s1.empty() && s2.empty();
}
}
OJ 链接
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
大体思路:
如果使用数组实现循环队列,如果一组数大于这个数组的长度那该怎么办?,可以使用覆盖的方法,前面的元素向前移动,出队列后,后面的在覆盖,但是时间复杂度就是O(n)。
那么既然是循环队列,那么循环两字就可以想到圆,我们可以把一组数据放进圆中,下标也放进去。
一个圆里面没满的情况下,直接出就行,那么一个圆放满了过后,怎么循环出尼?
1、首先设置两个变量,front,rear;
> front指向队列的头部
> rear指向队列的尾部
从图可知:
1、front和rear相遇是满还是空尼?
2、front怎么从7小标走到0小标?
(1)、规定相遇为null
>首先可以浪费一个格子,rear下一个front 就是 满
(2)、利用公式:(rear+1)%length
完整代码:
class MyCircularQueue {
private int[] elem;
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)% elem.length;
return true;
}
public boolean isFull() {
if((this.rear+1)% elem.length==this.front) {
return true;
}
return false;
}
//出队列
public boolean deQueue() {
if(isEmpty()) {
return false;
}
this.front=(this.front+1)% elem.length;
return true;
}
public boolean isEmpty() {
if(this.front==this.rear) {
return true;
}
return false;
}
//得到队头元素 相当于 peek()
public int Front() {
if(isEmpty()) {
return -1;
}
int val=this.elem[this.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];
}
}
铁汁们,觉得笔者写的不错的可以点个赞哟❤,收藏关注呗,你们支持就是我写博客最大的动力!!!!