运用offer(),poll(),peek()方法 。接收类型都与尖括号里的类型参数一至,E类型代表返回值,也与尖括号里类型参数一至。
运行结果
官方给出的Queue方法
分成三组来看,每组方法是差不多的用法,我们更倾向于用右边这三个方法
如:第一组add方法如果容量受限就会抛异常。offer在容量受限的情况不抛异常。(用offer方法较多一点)
LinkedList<Integer> queue = new LinkedList<>();这一种使用的方法更多,可以用LinkedList的方法
Queue<Integer> queue = new LinkedList<>();这种只能用Queue的方法
LinkedList之所以方法很多是因为不仅实现了Queue接口还实现了Deque接口,Deque是一个双端队列。
所以LinkedList这个集合类功能很多 可以 当队列 当链表(可以是双向链表,也可以是单链表)当栈。
问:用单链表 实现队列,问入队采用 头插 还是 尾插?
答:双链表 出队 入队时间复杂度都是O(1)。单链表 用尾插法实现队列,尾巴入时间复杂度O(n),头出时间复杂度O(1)。
力扣
难度中等
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k)
: 构造器,设置队列长度为 k 。Front
: 从队首获取元素。如果队列为空,返回 -1 。Rear
: 获取队尾元素。如果队列为空,返回 -1 。enQueue(value)
: 向循环队列插入一个元素。如果成功插入则返回真。deQueue()
: 从循环队列中删除一个元素。如果成功删除则返回真。isEmpty()
: 检查循环队列是否为空。isFull()
: 检查循环队列是否已满。示例:
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
思路
这是一个模型
从rear入队,从front出队。初始的时候让rear 和 front都指向0下标。rear在0下标插入元素的时候自己走在1下标,rear插入元素的时候始终站在空的格子上。
法2:也可以用usedsize ==length来判断是不是满了
class MyCircularQueue {
private int[] elem;
private int front;//表示队头下标
private int rear;//表示队尾下标
/**
* 构造方法
* @param k K个大小
*/
public MyCircularQueue(int k) {
elem = new int[k+1];//这里一定要让k加1
//让原本数组个数加一个空的位置
}
/**
* 入队
* 1、判断是不是满的?
* 2、把当前需要存放的元素放到rear下标的地方。
* @param value
* @return
*/
public boolean enQueue(int value) {
if(isFull()) {
return false;
}
this.elem[rear] = value;
//注意这里 不要出错!不要让rear++;如果在最后位置要走到0位置,++就不对。
rear = (rear+1) % elem.length;
return true;
}
/**
* 出队
* @return
*/
public boolean deQueue() {
if(isEmpty()) {
return false;
}
front = (front+1) % elem.length;
return true;
}
/**
* 得到队头元素
* @return
*/
public int Front() {
if(isEmpty()) {
return -1;
}
return elem[front];
}
/**
* 得到队尾元素
* @return
*/
public int Rear() {
if(isEmpty()) {
return -1;
}
int index = (rear == 0) ? (elem.length-1) : (rear-1);
return elem[index];
}
/**
* 当前循环队列是否为空
* @return
*/
public boolean isEmpty() {
return rear == front;
}
/**
* 判断当前队列是否为满
* 浪费一个空间来表示满
* @return
*/
public boolean isFull() {
if( (rear+1)%elem.length == front ) {
return true;
}
return false;
}
}
难度简单
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(
push
、top
、pop
和empty
)。实现
MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False来源:力扣(LeetCode)
思路:
题意给两个队列,要做到有栈的功能。
如图给定qu1,qu2两个队列。队列的特点是 先进先出(像是生活中排队)。栈的特点是 先进后出。
1.先把给的一组元素存到一个队列里。2.根据队列先进先出,把存进队列的元素 出队列 到另一个队列,但是留出最后一个元素(图中的45)接收给他出队列。
这样就做到了栈的功能:先进后出。
class MyStack {
private Queue<Integer> qu1;
private Queue<Integer> qu2;
public MyStack() {
qu1 = new LinkedList<>();
qu2 = new LinkedList<>();
}
/**
入到不为空的队列当中
如果都为空 放到qu1当中
*/
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() {
//1、先要判断 当前 “栈” 是否为空
if(empty()) {
return -1;
}
if(!qu1.isEmpty()) {
//出这个不为空的队列,最后一个元素最终保存在tmp
//q1的size一直在变,所以拿到前面算
int size = qu1.size();
for(int i = 0;i < size-1;i++) {
// int tmp = qu1.poll();
// qu2.offer(tmp);
qu2.offer(qu1.poll());
}
return qu1.poll();
} else {
//出这个不为空的队列,出size-1
int size = qu2.size();
for(int i = 0;i < size-1;i++) {
qu1.offer(qu2.poll());
}
return qu2.poll();
}
}
public int top() {
//1、先要判断 当前 “栈” 是否为空
if(empty()) {
return -1;
}
if(!qu1.isEmpty()) {
int size = qu1.size();
int tmp = -1;
for(int i = 0;i < size;i++) {
tmp = qu1.poll();
qu2.offer(tmp);
}
return tmp;
} else {
int size = qu2.size();
int tmp = -1;
for(int i = 0;i < size ;i++) {
tmp = qu2.poll();
qu1.offer(tmp);
}
return tmp;
}
}
public boolean empty() {
if(qu1.isEmpty() && qu2.isEmpty()) {
return true;
}
return false;
}
}
难度简单
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
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(双端队列)来模拟一个栈,只要是标准的栈操作即可。来源:力扣(LeetCode)
示例 1:
输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]来源:力扣(LeetCode)
思路:1.入队的时候放到第一个栈当中。2.出队的时候出第二个栈当中的。如果第二个栈里面没有元素,那就把第一个栈里面的都倒过来。
import java.util.Stack;
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);
}
//如果第二个栈不为空,则出栈顶元素。否则,将第一个栈的元素全部导入第2个栈
public int pop() {
//两个栈都为是空的
if(empty()) {
return -1;
}
if(s2.empty()) {
//那么就把s1里面的数据全部导过来
while(!s1.empty()) {
s2.push(s1.pop());
}
}
//s2一定是不为空的
return s2.pop();
}
public int peek() {
//两个栈都为是空的
if(empty()) {
return -1;
}
if(s2.empty()) {
//那么就把s1里面的数据全部导过来
while(!s1.empty()) {
s2.push(s1.pop());
}
}
//s2一定是不为空的
return s2.peek();
}
public boolean empty() {
return s1.empty() && s2.empty();
}
}
难度中等
设计一个支持
push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。实现
MinStack
类:
MinStack()
初始化堆栈对象。void push(int val)
将元素val推入堆栈。void pop()
删除堆栈顶部的元素。int top()
获取堆栈顶部的元素。int getMin()
获取堆栈中的最小元素。示例 1:
输入: ["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.
题意是用O(1)时间复杂度,就能知道最小值是几。
入栈的时候要和minStack比较,出栈也要和minStack比较。
import java.util.Stack;
class MinStack {
private Stack<Integer> s1;
private Stack<Integer> minStack;
public MinStack() {
s1 = new Stack<>();
minStack = new Stack<>();
}
/**
s1这个栈 一定要放元素的
*/
public void push(int val) {
s1.push(val);
if(minStack.empty()) {
minStack.push(val);
}else{
int x = minStack.peek();
//这里一定要取等号
if(val <= x) {
minStack.push(val);
}
}
}
public void pop() {
int x = s1.pop();
int x2 = minStack.peek();
if(x == x2) {
minStack.pop();
}
}
//获取当前的栈顶元素不删除 ,不是最小栈的栈顶元素
public int top() {
return s1.peek();
}
public int getMin() {
return minStack.peek();
}
}