public static void main(String[] args) {
Stack stack = new Stack<>();
//压栈
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
//查看栈顶元素
System.out.println(stack.peek());
//出栈
int ret = stack.pop();
System.out.println(ret); //4
ret = stack.pop();
System.out.println(ret); //3
ret = stack.pop();
System.out.println(ret); //2
ret = stack.pop();
System.out.println(ret); //1
//判断栈是否为空
System.out.println(stack.empty());
//此时栈为空 如果 查看栈顶元素 或者 出栈 会报异常(EmptyStackException)
System.out.println(stack.peek());
System.out.println(stack.pop());
}
运行结果:
Queue
| 错误处理 | 抛出异常 | 返回特殊值 |
| :-- | :-- | :-- |
| 入队列 | add(e) | offer(e) |
| 出队列 | remove() | poll() |
| 队首元素 | element() | peek() |
Deque
| 头部/尾部 | 头部元素(队首) | 尾部元素(队尾) |
| — | — | — |
| 错误处理 | 抛出异常 | 返回特殊值 | 抛出异常 | 返回特殊值 |
| 入队列 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) |
| 出队列 | removeFirst() | pollFirst() | removeLast() | pollLast() |
| 获取元素 | getFirst() | peekFirst() | getLast() | peekLast() |
总结:
Stack:
push
,pop
,peek
.当当前是一个空栈的,再去pop或者peek就会产生异常.
Queue:
add
,remove
,element
如果当前操作失败就会抛出异常;
offer
,poll
,peek
如果操作失败就会返回一个错误值;
==================================================================================
LeetCode 20:
描述:
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
-
左括号必须用相同类型的右括号闭合。
-
左括号必须以正确的顺序闭合。
解题思路:
**1. 遍历字符串,依次取出字符串中的字符.
1.1 如果取出的字符串为左括号例如’(’,’[’,’{’.就放入栈中
1.2 如果取出的字符串为右括号例如’)’,’]’,’}’.就和栈顶元素比较是否匹配.
a) 匹配就出栈,然后继续遍历.
b) 不匹配就直接返回false
1.3 如果栈为空,且取出的字符是右括号,则返回false没有例如字符串
"]()"
2. 遍历结束后,判断是否栈为空
2.1 如果为空 则满足题意 return true;
2.2 如果不为空 表示没有足够匹配的字符, return false; 如字符串
"["
**
画图解析:
代码实现:
public boolean isValid(String str) {
Map<Character,Character> map = new HashMap<>();
map.put(‘(’,‘)’);
map.put(‘[’,‘]’);
map.put(‘{’,‘}’);
//1.先创建一个栈,栈中保存字符类型即可
Stack stack = new Stack<>();
//2.遍历字符串的每个字符
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
//3.判断字符 ch 是否为左括号,如果是,就入栈
if (ch == ‘(’ || ch == ‘[’ || ch == ‘{’){
stack.push(ch);
continue;//进入下次循环,取出下一个字符
}
if(stack.empty()){
//如果ch不是左括号,且栈为空,则不是合法括号
return false;
}
//4.判断ch是否是右括号,如果是,就取栈顶元素比较是否相等
char top = stack.pop();//栈顶元素
//以下是3种情况合法情况 – 写法1
/*if(top == ‘(’ && ch == ‘)’) {
continue;
}
if(top == ‘[’ && ch == ‘]’) {
continue;
}
if(top == ‘{’ && ch == ‘}’) {
continue;
}*/
// 判断合法情况 – 写法2
if(map.get(top) == ch){
continue;
}
//如果三种情况都不满足,表示不是合法情况
return false;
}
//遍历完成后 如果栈为空 则满足条件
if(stack.empty()) {
return true;
}
//否则就不合法
return false;
}
LeetCode 225:
描述:
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
-
void push(int x) 将元素 x 压入栈顶。
-
int pop() 移除并返回栈顶元素。
-
int top() 返回栈顶元素。
-
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
注意:
-
你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
-
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
解题思路:
**1. 用两个队列来模拟一个栈的效果,引用两个队列 A 和 B .
2. 入栈 : 直接把元素入队到A中即可
3. 出栈 : 因为队列是先进先出的,栈是后进先出的,可以让 A队列 元素出队列然后入队列到 B队列 中,直到A队列中最后一个元素的时候,直接出队列,就实现了后进先出.然后要让A和B交换,始终让入栈到A队列中.
4. 取栈顶元素 : 取栈顶元素就是 出栈 的元素, 不过取栈顶元素要把这个元素返回去
5. 判断是否为空 : A 和 B都为空的时候 就是空栈**
画图解析:
代码实现:
import java.util.LinkedList;
import java.util.Queue;
public class MyStackByDoubleQueue {
private Queue A = new LinkedList<>();
private Queue B = new LinkedList<>();
public void push(int x) {
// x往A中入队列即可
A.offer(x);
}
public Integer pop() {
if (empty()){
return null;
}
// 把A中的元素往 B 中放
while(A.size() > 1) {
Integer font = A.poll();
B.offer(font);
}
//当循环结束后,A 中 应该只剩1个元素
//这个元素就应该是被出栈的元素
int ret = A.poll();
//交换A和B
swapAB();
return ret;
}
private void swapAB(){
Queue tmp = A;
A = B;
B = tmp;
}
public Integer top() {
if (empty()){
return null;
}
// 把A中的元素往 B 中放
while(A.size() > 1) {
Integer font = A.poll();
B.offer(font);
}
//当循环结束后,A 中 应该只剩1个元素
//这个元素就应该是被出栈的元素
int ret = A.poll();
B.offer(ret); // top 和 pop的区别就是 top要把元素返回去,pop不需要返回去
//交换A和B
swapAB();
return ret;
}
public boolean empty() {
return A.isEmpty() && B.isEmpty();
}
}
LeetCode 232:
描述:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
-
void push(int x) 将元素 x 推到队列的末尾
-
int pop() 从队列的开头移除并返回元素
-
int peek() 返回队列开头的元素
-
boolean empty() 如果队列为空,返回 true ;否则,返回 false
解题思路:
**1. 引用2个栈A和B,A专门用来入队列;B专门用来出队列
2. 实现入队列: 先把B中的所有元素都放到A中(因为出栈的时候元素会放入B中),然后直接往A里入栈.
3. 实现出队列: 后进先出的栈实现先进先出的队列,要让A中的所有元素移入B中,先出的的元素就是后进的,此时栈顶就是就是最先进入的元素,B中出栈操作即可
4. 实现取队首元素: 同出队列操作,把A所有元素放入B中,然后取B的栈顶元素就是队首元素.
5. 判空: A 和 B 都为空.**
画图解析:
代码实现:
import java.util.Stack;
public class MyQueueByDoubleStack {
private Stack A = new Stack<>();
private Stack B = new Stack<>();
public void push(int x) {
//1.先将B中的元素 放入 A 中
while (!B.isEmpty()){
int tmp = B.pop();
A.push(tmp);
}
//2.把新元素放入A中
A.push(x);
}
public Integer pop() {
//1.如果为空 直接返回
if(empty()){
return null;
}
//2.把A中的元素都给B
while(!A.isEmpty()){
int tmp = A.pop();
B.push(tmp);
}
//3.针对B进行出栈
return B.pop();
}
public Integer peek() {
//1.如果为空 直接返回
if(empty()){
return null;
}
//2.把A中的元素都给B
while(!A.isEmpty()){
int tmp = A.pop();
B.push(tmp);
}
//3.取B的栈顶元素
return B.peek();
}
public boolean empty() {
return A.isEmpty() && B.isEmpty();
}
}
LeetCode 155:
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
-
push(x) —— 将元素 x 推入栈中。
-
pop() —— 删除栈顶的元素。
-
top() —— 获取栈顶元素。
-
getMin() —— 检索栈中的最小元素。
解题思路:
**1. 引用2个栈A和B, A按照正常栈的规则入栈出栈,B存放的是A的最小值以及A历史的最小值
2. 实现入栈操作: A中: 直接入栈 . B中: 取要入栈的值 和 B栈顶元素比较,把较小值入栈到B中.
3. 实现出栈操作: A 和 B 一起出栈
4. 实现取栈顶元素操作: 直接取 A 栈顶元素
5. 实现取最小值操作: 直接取 B 栈顶元素**
画图解析:
代码实现:
import java.util.Stack;
public class MinStack {
private Stack A = new Stack<>();
private Stack B = new Stack<>();
public void push(int x){
//A 直接入栈
A.push(x);
//如果B为空 直接入栈
if(B.isEmpty()){
B.push(x);
return;
}
//如果B不为空,比较x和B栈顶的较小值,将较小值入栈
int min = B.peek();
min = min < x ? min : x;
B.push(min);
}
public Integer pop(){
//如果A为空 直接返回
if(A.isEmpty()){
return null;
}
//B和A同时出栈
B.pop();
return A.pop();
}
public Integer top(){
//如果A为空 直接返回
if(A.isEmpty()){
return null;
}
return A.peek();
}
public Integer getMin(){
//如果B为空 直接返回
if(B.isEmpty()){
return null;
}
//B的栈顶即使最小元素
return B.peek();
}
}
LeetCode 622:
描述:
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
-
MyCircularQueue(k): 构造器,设置队列长度为 k 。
-
Front: 从队首获取元素。如果队列为空,返回 -1 。
-
Rear: 获取队尾元素。如果队列为空,返回 -1 。
-
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
-
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
-
isEmpty(): 检查循环队列是否为空。
-
isFull(): 检查循环队列是否已满。
解题思路:
**1. 循环队列 运用数组实现. head和tail是下标,
head
位置始终都是队首的元素;tail
位置始终都是队尾的下一个元素 有效元素个数[ head, tail) 左闭右开
2. 入队列 : 把新元素放到 tail 位置上,同时 tail++.
3. 出队列 : 取出 head 位置的元素,同时 head++.
4. 空队列 : 有效元素个为0
5. 满队列 : 有效元素个数等于数组长度
6. 注意当head 和 tail达到 元素上线时,回到最开始的位置.**
画图解析:
代码实现:
public class MyCircularQueue {
private int[] elem;
private int head = 0;//队首元素下标
private int tail = 0;//队尾下一个元素下标
private int size = 0;//有效元素个数
/**
-
构造器,设置队列长度为 k 。
-
@param k 队列长度
*/
public MyCircularQueue(int k) {
this.elem = new int[k];
}
/**
-
向循环队列插入一个元素。如果成功插入则返回真。
-
@param value 插入元素
-
@return
*/
public boolean enQueue(int value) {
//队满就无法入队 返回false
if(size == elem.length){
return false;
}
elem[tail] = value;
tail++;
//tail>=队列长度 要归零
if(tail >= elem.length){
tail = 0;
}
size++;
return true;
}
/**
-
从循环队列中删除一个元素。如果成功删除则返回真。
-
队头出
-
@return
*/
public boolean deQueue() {
//如果队列为空 没有要删除的返回false
if(size == 0){
return false;
}
head++;
//head>=队列长度 要归零
if(head >= elem.length){
head = 0;
}
size–;
return true;
}
/**
-
从队首获取元素。如果队列为空,返回 -1 。
-
@return
*/
public int Front() {
if(size == 0){
return -1;
}
return elem[head];
}
/**
-
获取队尾元素。如果队列为空,返回 -1 。
-
@return
*/
public int Rear() {
if(size == 0){
return - 1;
}
if(tail==0) return elem[elem.length - 1];
return elem[tail-1];
}
/**
-
检查循环队列是否为空。
-
@return
*/
public boolean isEmpty() {
if(size == 0){
return true;
}
return false;
}
/**
-
检查循环队列是否已满
-
@return
*/
public boolean isFull() {
if(size == elem.length){
return true;
}
return false;
}
}
LeetCode 150:
剑指 Offer Ⅱ 036:
描述:
根据 逆波兰表示法,求表达式的值。
有效的算符包括+、-、*、/
。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
解题思路:
**1. 中缀记法 是一个通用的算术或逻辑公式表示方法,中缀表达式如
3 + 4
前缀表达式如
+ 3 4
, 后缀表达式如3 4 +
. 前缀和后缀表达式都表示3+4
2. 用栈解决逆波兰表达式, 遍历字符数组
① 如果为数字 入栈
② 如果为
+、-、*、/
出栈两个数字 完成对应操作,然后将得到的数据 入栈
3. 注意完成对应
+、-、*、/
操作时,是后一个出栈的数据+、-、*、/
前一个出栈的数据**
画图解析:
代码实现:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。
还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
e_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd3d6enp6enp6enp6enp6,size_20,color_FFFFFF,t_70,g_se,x_16)
代码实现:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-au8w7Bv5-1713712114981)]
[外链图片转存中…(img-En2hchXJ-1713712114982)]
[外链图片转存中…(img-PeXc8jYQ-1713712114982)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。
还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-4wFOZUAu-1713712114983)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!