【算法训练-栈 一】【结构特性】有效的括号、最小栈(包含Min函数的栈)

简介: 【算法训练-栈 一】【结构特性】有效的括号、最小栈(包含Min函数的栈)

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【栈的使用】,使用【栈】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为:目标公司+最近一年+出现频率排序,由高到低的去牛客TOP101去找,只有两个地方都出现过才做这道题(CodeTop本身汇聚了LeetCode的来源),确保刷的题都是高频要面试考的题。

名曲目标题后,附上题目链接,后期可以依据解题思路反复快速练习,题目按照题干的基本数据结构分类,且每个分类的第一篇必定是对基础数据结构的介绍

有效括号序列【EASY】

非常适合栈这种数据结构的一道题

题干

解题思路

括号的匹配规则应该符合先进后出原理:最外层的括号即最早出现的左括号,也对应最晚出现的右括号,即先进后出,因此可以使用同样先进后出的栈:遇到左括号就将相应匹配的右括号加入栈中,后续如果是合法的,右括号来的顺序就是栈中弹出的顺序

  • step 1:创建辅助栈,遍历字符串。
  • step 2:每次遇到小括号的左括号、中括号的左括号、大括号的左括号,就将其对应的右括号加入栈中,期待在后续遇到。
  • step 3:如果没有遇到左括号但是栈为空,说明直接遇到了右括号,不合法。
  • step 4:其他情况下,如果遇到右括号,刚好会与栈顶元素相同,弹出栈顶元素继续遍历。
  • step 5:理论上,只要括号是匹配的,栈中元素最后是为空的,因此检查栈是否为空即可最后判断是否合法。

代码实现

给出代码实现基本档案

基本数据结构数组

辅助数据结构哈希表

算法迭代

技巧哈希查找

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param s string字符串
     * @return bool布尔型
     */
    public boolean isValid (String s) {
        // 1 定义辅助栈
        Stack<Character> stack = new Stack<Character>();
        // 2 遍历字符串字符
        for (int i = 0; i < s.length(); i++) {
            //遇到左小括号
            if (s.charAt(i) == '(') {
                //期待遇到右小括号
                stack.push(')');
            }
            //遇到左中括号
            else if (s.charAt(i) == '{') {
                //期待遇到右中括号
                stack.push('}');
            }
            //遇到左大括号
            else if (s.charAt(i) == '[') {
                //期待遇到右大括号
                stack.push(']');
            }
            //没有遇到左括号的情况下来了个右括号||或者遇到的右边括号和栈顶元素不相同则认为非法
            else if (stack.isEmpty() || stack.pop() != s.charAt(i)) {
                return false;
            }
        }
        // 3 字符串遍历完成后,且栈中没有元素则全部匹配完成,括号序列合法
        return stack.isEmpty();
    }
}

复杂度分析

时间复杂度:遍历了一遍字符串,时间复杂度为O(N)

空间复杂度:使用了辅助栈,空间复杂度为O(N)

最小栈(包含min函数的栈)【EASY】

表达栈操作的一道题

题干

解题思路

我们都知道栈结构的push、pop、top操作都是O(1),但是min函数做不到,于是想到在push的时候就将最小值记录下来,由于栈先进后出的特殊性,我们可以构造一个单调栈,保证栈内元素都是递增的,栈顶元素就是当前最小的元素

step 1:使用一个栈记录进入栈的元素,正常进行push、pop、top操作。

step 2:使用另一个栈记录每次push进入的最小值

step 3:每次push元素的时候与第二个栈的栈顶元素比较,若是较小,则进入第二个栈,若是较大,则第二个栈的栈顶元素再次入栈,因为即便加了一个元素,它依然是最小值。于是,每次访问最小值即访问第二个栈的栈顶

代码实现

给出代码实现基本档案

基本数据结构数组

辅助数据结构哈希表

算法迭代

技巧哈希查找

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

import java.util.*;
import java.util.Stack;
public class Solution {
    // 1 初始化操作栈和最小栈
    private Stack<Integer> stack = new Stack<Integer>(); ;
    private Stack<Integer> minStack = new Stack<Integer>();;
    public void push(int node) {
        // 1 push时操作栈push元素,空栈或当前值小于操作栈顶元素时,当前值压入最小栈
        if (minStack.isEmpty() || node < minStack.peek()) {
            minStack.push(node);
        } else {
            // 否则将操作栈顶元素压入最小栈
            minStack.push(minStack.peek());
        }
        // 2 无论如何,元素要压入操作栈
        stack.push(node);
    }
    public void pop() {
        stack.pop();
        minStack.pop();
    }
    public int top() {
        return stack.peek();
    }
    public int min() {
        return minStack.peek();
    }
}

复杂度分析

时间复杂度:没有循环和递归,任何操作都是常数阶,时间复杂度为O(1)

空间复杂度:使用了辅助栈,空间复杂度为O(N)

拓展知识:栈的基本操作

Java中栈的操作方法通常是通过使用java.util.Stack类或java.util.Deque接口的实现类来完成的。以下是一些常见的栈操作方法:

  1. 创建一个栈:
Stack<Integer> stack = new Stack<>();
  1. 入栈操作(push):
stack.push(1);
stack.push(2);
stack.push(3);
  1. 出栈操作(pop):
int top = stack.pop(); // 弹出栈顶元素并将其存储在变量中
  1. 查看栈顶元素但不移除它(peek):
int top = stack.peek();
  1. 检查栈是否为空(isEmpty):
boolean isEmpty = stack.isEmpty();
  1. 获取栈的大小(size):
int size = stack.size();
  1. 清空栈(clear):
stack.clear();
  1. 使用Deque实现栈:
    你也可以使用java.util.Deque接口的实现类,如java.util.ArrayDeque来模拟栈的行为。以下是使用ArrayDeque实现栈的示例:
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.push(2);
stack.push(3);
int top = stack.pop();
int size = stack.size();
boolean isEmpty = stack.isEmpty();

注意:在Java中,推荐使用Deque接口的实现类来模拟栈,因为Stack类是Vector的子类,而Vector在多线程环境下不是线程安全的,因此不推荐在多线程环境中使用Stack类。

相关文章
|
2天前
|
负载均衡 算法 应用服务中间件
面试题:Nginx有哪些负载均衡算法?Nginx位于七层网络结构中的哪一层?
字节跳动面试题:Nginx有哪些负载均衡算法?Nginx位于七层网络结构中的哪一层?
49 0
|
2天前
|
存储 监控 NoSQL
Redis处理大量数据主要依赖于其内存存储结构、高效的数据结构和算法,以及一系列的优化策略
【5月更文挑战第15天】Redis处理大量数据依赖内存存储、高效数据结构和优化策略。选择合适的数据结构、利用批量操作减少网络开销、控制批量大小、使用Redis Cluster进行分布式存储、优化内存使用及监控调优是关键。通过这些方法,Redis能有效处理大量数据并保持高性能。
22 0
|
2天前
|
算法 网络协议
【计网·湖科大·思科】实验三 总线型以太网的特性、集线器和交换机的区别、交换机的自学习算法
【计网·湖科大·思科】实验三 总线型以太网的特性、集线器和交换机的区别、交换机的自学习算法
8 1
|
2天前
|
存储 算法
数据结构与算法 栈与队列
数据结构与算法 栈与队列
12 0
数据结构与算法 栈与队列
|
2天前
|
网络协议 算法 数据库
【专栏】OSPF是广泛应用的链路状态路由协议,通过分层网络结构和SPF算法实现高效路由。强烈建议收藏!
【4月更文挑战第28天】OSPF是广泛应用的链路状态路由协议,通过分层网络结构和SPF算法实现高效路由。其关键特性包括区域划分、链路状态数据库、邻居关系和路由更新。工作过程涉及邻居发现、信息交换、数据库构建、路由计算及收敛。理解OSPF对于网络管理和规划具有重要意义。
|
2天前
|
机器学习/深度学习 搜索推荐 算法
实现手机 app 千人千面的特性,背后有哪些机器学习算法
实现手机 app 千人千面的特性,背后有哪些机器学习算法
20 0
|
2天前
|
存储 算法
【算法与数据结构】深入解析二叉树(二)之堆结构实现
【算法与数据结构】深入解析二叉树(二)之堆结构实现
|
2天前
|
存储 缓存 算法
【算法与数据结构】栈的实现详解
【算法与数据结构】栈的实现详解
|
2天前
|
存储 算法 编译器
【数据结构】栈算法(算法原理+源码)
【数据结构】栈算法(算法原理+源码)
【数据结构】栈算法(算法原理+源码)
|
2天前
|
存储 算法 C语言
数据结构与算法:栈
朋友们大家好啊,在链表的讲解过后,我们本节内容来介绍一个特殊的线性表:栈,在讲解后也会以例题来加深对本节内容的理解