栈的经典算法问题(算法村第四关白银挑战)

括号匹配问题

有效的括号

20. 有效的括号 - 力扣(LeetCode)

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成
利用HashMap
public boolean isValid(String s)
    {
        HashMap<Character, Character> hashMap = new HashMap<>();

        //key为左括号,value为右括号
        hashMap.put('(',')');
        hashMap.put('[',']');
        hashMap.put('{','}');

        ArrayDeque<Character> stack = new ArrayDeque<>();

        for (int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);

            if(hashMap.containsKey(c))  //c是左括号
                stack.push(c);  //左括号入栈
            else    //c是右括号
            {
                //栈空,或者该右括号与栈顶的左括号不匹配
                if (stack.isEmpty() || c != hashMap.get(stack.peek()))
                    return false;
                else //匹配
                    stack.pop();    //栈顶的左括号出栈
            }
        }

        //循环结束后,若栈空则s是括号有效的字符串,否则说明还有左括号没匹配
        return stack.isEmpty();
    }
非HashMap版
public boolean isLeftBracket(char c)
    {
        return c == '(' || c == '{' || c == '[';
    }

    public char partner(char c)
    {
        switch(c)
        {
            case ')': return '(';
            case '}': return '{';
            case ']': return '[';
            default: return ' ';
        }
    }

    public boolean isValid(String s) 
    {
        //括号总数必须是偶数
        if(s.length() % 2 != 0)
            return false;

        Stack<Character> stack = new Stack<>();

        for(int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);

            if(isLeftBracket(c))    //c是左括号
                stack.push(c);
            else    //c是右括号
            {   
                //栈空,或者该右括号与栈顶的左括号不匹配
                if(stack.isEmpty() || stack.peek() != partner(c))
                    return false;
                else    //匹配
                    stack.pop();  //栈顶的左括号出栈
            }
        }

        return stack.isEmpty(); //栈空则s是括号有效的字符串,栈不空说明还有左括号没匹配
    }

括号生成

22. 括号生成 - 力扣(LeetCode)

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

示例 2:

输入:n = 1
输出:["()"]

提示:

  • 1 <= n <= 8
深搜,做减法

在这里插入图片描述

public List<String> generateParenthesis(int n)
{
    //特判
    if (n == 0)
        return null;

    //结果集
    ArrayList<String> res = new ArrayList<String>();

    //深搜,找出全部有效括号组合
    DFS(res, n, n, "");

    return res;
}

/**
 * @param res 结果集
 * @param left 左括号还能用几个
 * @param right 右括号还能用几个
 * @param curStr 当前递归所得到的字符串
 */
public static void DFS(List<String> res, int left, int right, String curStr)
{
    //递归终止;将一种组合添加到结果集
    if (left == 0 && right == 0)
    {
        res.add(curStr);
        return;
    }

    //尝试使用右括号后,若左括号剩余数量大于右括号剩余数量,则“剪枝”(否则会违背有效括号的定义)
    if (left > right)
        return;

    //优先使用左括号
    if (left > 0)
        DFS(res, left - 1, right, curStr + "(" );

    //使用右括号
    if (right > 0)
        DFS(res, left, right - 1, curStr +")" );
}
深搜,做加法

在这里插入图片描述

public List<String> generateParenthesis(int n)
{
    //特判
    if (n == 0)
        return null;

    //结果集
    ArrayList<String> res = new ArrayList<String>();

    //深搜,寻找全部有效括号组合
    DFS(res, 0, 0, "", n);

    return res;
}

/**
 * @param res 结果集
 * @param left 左括号使用了几个
 * @param right 右括号使用使用了几个
 * @param curStr 当前递归所得到的字符串
 * @param n 题目所给的括号生成对数
 */
public static void DFS(List<String> res, int left, int right, String curStr, int n)
{
    //递归终止;将一种组合添加到结果集
    if (left == n && right == n)
    {
        res.add(curStr);
        return;
    }

    //尝试使用右括号后,若左括号使用数量小于右括号使用数量,则“剪枝”(否则会违背有效括号的定义)
    if (left < right)
        return;

    //优先使用左括号
    if (left < n)
        DFS(res, left + 1, right, curStr + "(", n);

    //使用右括号
    if (right < n)
        DFS(res, left, right + 1, curStr +")", n);
}
广搜
/**
 * 队列结点
 */
class Node
{
    String curStr;
    int left;   //左括号还剩几个没用
    int right; //右括号还剩几个没用

    public Node(String curStr, int left, int right)
    {
        this.curStr = curStr;
        this.left = left;
        this.right = right;
    }
}

public List<String> generateParenthesis_3(int n)
{
    //特判,否则n==0时下面的算法会返回""
    if(n == 0)
        return null;

    //结果集
    ArrayList<String> res = new ArrayList<String>();

    ArrayDeque<Node> queue = new ArrayDeque<>();
    //初始结点入队
    queue.offer(new Node("", n, n));

    while (!queue.isEmpty())
    {
        //队头元素出队
        Node curNode = queue.poll();

        //生成了一组有效括号
        if(curNode.left == 0 && curNode.right == 0)
            res.add(curNode.curStr);

        //优先使用左括号
        if (curNode.left > 0)
            queue.offer(new Node(curNode.curStr + "(", curNode.left - 1, curNode.right));

        //左括号少于右括号的情况下,才能使用右括号
        if (curNode.right > 0 && curNode.left < curNode.right)
            queue.offer(new Node(curNode.curStr + ")", curNode.left, curNode.right - 1));
    }

    return res;
}

最小栈

155. 最小栈 - 力扣(LeetCode)

设计一个支持 pushpoptop 操作,并能在常数时间内检索到最小元素的栈。

实现 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.

提示:

  • -231 <= val <= 231 - 1
  • poptopgetMin 操作总是在 非空栈 上调用
  • push, pop, top, and getMin最多被调用 3 * 104

建立一个存储val的元素栈和一个辅助栈,辅助栈与元素栈同步push和pop,并存储每个val入栈后对应的最小值

以空间换时间

ArrayDeque<Integer> stack;  //元素栈

ArrayDeque<Integer> minStack;   //辅助栈

public MinStack()
{
    stack = new ArrayDeque<>();
    minStack = new ArrayDeque<>();
    minStack.push(Integer.MAX_VALUE);
}

public void push(int val)
{
    stack.push(val);
    minStack.push(Math.min(minStack.peek(), val));
}

public void pop()
{
    stack.pop();
    minStack.pop();
}

public int top()
{
    return stack.peek();
}

public int getMin()
{
    return minStack.peek();
}

最大栈

716. 最大栈 - 力扣(LeetCode)

题目要求与【最小栈】基本相同,难度提升在于要我们实现**“popMax():检索并返回栈中最大元素,并将其移除。如果有多个最大元素,只要移除最靠近栈顶的那个。”**,以及数据增强,对时间效率要求更高

元素栈+辅助栈

对时间要求不严格的情况下,可以沿用最小栈的解法,并建立一个临时栈实现popMax()

public class MaxStack
{
    ArrayDeque<Integer> stack;  //元素栈
    ArrayDeque<Integer> maxStack;   //辅助栈

    public MaxStack()
    {
        stack = new ArrayDeque<>();
        maxStack = new ArrayDeque<>();
        maxStack.push(Integer.MIN_VALUE);
    }

    public void push(int x)
    {
        stack.push(x);
        maxStack.push(Math.max(maxStack.peek(), x));
    }

    public int pop()
    {
        maxStack.pop();
        return stack.pop();
    }

    public int top()
    {
        return stack.peek();
    }

    public int peekMax()
    {
        return maxStack.peek();
    }

    public int popMax()
    {
        int max = peekMax();

        ArrayDeque<Integer> tempStack = new ArrayDeque<>();

        //将元素栈stack中在最大元素之上的所有元素一次倾倒、存储起来。辅助栈需要同步操作
        while (top() != max )
            tempStack.push(pop());

        //找到距离栈顶最近的最大元素,删除它
        pop();

        //将临时栈中的元素倒回去
        while (!tempStack.isEmpty())
            push(tempStack.pop());

        return max;
    }
}
用链表结点同时存储val和max

逻辑与第一种解法一致,但一样无法通过最后一个严格的测试用例

class Node
{
    int val;    //元素的值
    int max;    //此时的最大值
    Node next;

    public Node(int val, int max, Node next) {
        this.val = val;
        this.max = max;
        this.next = next;
    }
}

class MaxStack_2
{
    Node head = null;  //指向表首元素
    public MaxStack_2(){}

    public void push(int x)
    {
        if (head == null)
            head = new Node(x, x, null);
        else    //x与之前的最大值比较,得出新的最大值
            head = new Node(x, Math.max(head.max, x), head);
    }

    public int pop()
    {
        int val = head.val;
        head = head.next;

        return val;
    }

    public int top()
    {
        return head.val;
    }

    public int peekMax()
    {
        return head.max;
    }

    public int popMax()
    {
        int Max = head.max;
        Node tempList = null;   //临时链表的头指针,作用与临时栈的栈顶指针相同

        while (head.val != Max)
        {
            Node suc = head.next;
            head.next = tempList;
            tempList = head;
            head = suc;
        }

        //删除最大元素
        head = head.next;

        //“倒回去”
        while (tempList != null)
        {
            push(tempList.val);
            tempList = tempList.next;
        }

        return Max;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/302745.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

滴水逆向1

八进制加法乘法表 EF11101111 j记住其映射关系 十进制的定义&#xff1a;由十个符号组成&#xff0c;分别是0 1 2 3 4 5 6 7 8 9 逢十进一。九进制的定义&#xff1a;由九个符号组成&#xff0c;分别是0 1 2 3 4 5 6 7 8 逢九进一。十六进制的定义&#xff1a;由十六个符号组成…

鸿蒙开发解决agconnect sdk not initialized. please call initialize()

文章目录 项目场景:问题描述原因分析:解决方案:总结:项目场景: 鸿蒙开发报错: agconnect sdk not initialized. please call initialize() 问题描述 报错内容为: 10-25 11:41:01.152 6076-16676 E A0c0d0/JSApp: app Log: 数据查询失败: {“code”:1100001,“messag…

在Kubernetes中优雅地导出和清理Ingress资源

引言 Kubernetes的Ingress资源是定义外部访问集群服务的规则。随着微服务架构和容器化技术的普及&#xff0c;Ingress作为路由流量的关键组件变得愈发重要。当我们需要在环境之间迁移Ingress资源或者备份当前的配置时&#xff0c;就会用到导出功能。然而&#xff0c;直接使用k…

听GPT 讲Rust源代码--compiler(29)

File: rust/compiler/rustc_const_eval/src/util/check_validity_requirement.rs 在Rust编译器的源代码中&#xff0c;rust/compiler/rustc_const_eval/src/util/check_validity_requirement.rs文件的作用是进行验证要求的检查。具体而言&#xff0c;该文件定义了函数check_val…

一文讲透使用Python绘制双纵轴线图

双纵轴线图主要用来展示两个因变量和一个自变量的关系&#xff0c;并且两个因变量的数值单位不同。具体来说&#xff0c;双纵轴线图是指在一幅图上有一个横轴和两个纵轴&#xff0c;适用于三个变量。两个纵轴分别表示一个变量&#xff0c;横轴变量同时适用于两个纵轴上的变量&a…

C++力扣题目--94,144,145二叉树非递归(迭代)遍历

为什么可以用迭代法&#xff08;非递归的方式&#xff09;来实现二叉树的前后中序遍历呢&#xff1f; 我们在栈与队列&#xff1a;匹配问题都是栈的强项 (opens new window)中提到了&#xff0c;递归的实现就是&#xff1a;每一次递归调用都会把函数的局部变量、参数值和返回地…

Azure Machine Learning - 人脸识别任务概述与技术实战

Azure AI 人脸服务提供了可检测、识别和分析图像中的人脸的 AI 算法。 人脸识别软件在许多不同情形中都十分重要&#xff0c;例如识别、无接触访问控制和实现隐私的人脸模糊。你可以通过客户端库 SDK&#xff0c;或者直接调用 REST API 使用人脸服务。 目录 一、人脸识别服务场…

Python print()函数高级用法和 len()函数详解:获取字符串长度或字节数

Python print()函数高级用法 我们使用 print() 函数时&#xff0c;都只输出了一个变量&#xff0c;但实际上 print() 函数完全可以同时输出多个变量&#xff0c;而且它具有更多丰富的功能。 print() 函数的详细语法格式如下&#xff1a; print (value,...,sep,end\n,filesys.s…

词嵌入位置编码的实现(基于pytorch)

背景介绍 在transformers架构当中&#xff0c;对于词向量的输入需要加上原本词对应的位置信息&#xff0c;作为输入到模型中训练的input&#xff0c;那具体的位置编码如何实现呢&#xff1f;本篇博客就跟大家一起分享一下对应的步骤 位置编码的公式 对于词向量的位置编码的方…

LaTex引用字体变色

使用下面这条语句进行修改。 ‘citecolor’改变参考文献颜色&#xff0c; ‘linkcolor’改变图标公式引用的颜色&#xff0c; ‘urlcolor’ 文本网站超链接颜色。 \usepackage[colorlinks,bookmarksopen,bookmarksnumbered,citecolorblue, linkcolorblue, urlcolorblue]{hyper…

黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目——第四部分

黑马程序员Java项目实战《瑞吉外卖》&#xff0c;轻松掌握springboot mybatis plus开发核心技术的真java实战项目——第四部分 1. 套餐管理1.1 新增套餐1.1.1 添加菜品数据回显 1.2 保存添加套餐1.3 套餐信息分页查询1.4 删除套餐1.5 需要自己单独实现的功能1.5.1 套餐管理的启…

leecode-代码随想录-学习笔记1

编程语言基础课&#xff0c;重新学习 kamacoder.com 基础语法&#xff1b;ACM输入输出通用模板&#xff1b;之前Java狂神说的学习笔记&#xff08;但是还是按照编程习惯用了C&#xff0c;感觉更底层好写代码&#xff09;。 正式开始&#xff1a; 下面按照题目-我的解答思路和…

深度解析Nginx负载均衡算法及配置实例

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

每天刷两道题——第十天

1.1和为k的子数组 给你一个整数数组 n u m s nums nums 和一个整数 k k k &#xff0c;请你统计并返回 该数组中和为 k k k 的子数组的个数 。子数组是数组中元素的连续非空序列。 输入&#xff1a;nums [1,2,3], k 3 输出&#xff1a;2 前缀和 1.2如何使用 前缀和的…

VSCode搭建 .netcore 开发环境

一、MacOS 笔者笔记本电脑上安装的是macOS High Sierra(10.13)&#xff0c;想要尝试一下新版本的.netcore&#xff0c;之前系统是10.12时&#xff0c;.netcore 3.1刚出来时安装过3.1版本&#xff0c;很久没更新了&#xff0c;最近.net8出来了&#xff0c;想试一下&#xff0c;…

【回溯算法】n-皇后

导航 题目来源题目描述示例思路完整代码 题目来源 n-皇后 题目描述 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一…

thinkphp学习02-目录结构、控制器、路由、配置文件

目录结构 www WEB部署目录&#xff08;或者子目录&#xff09; ├─app 应用目录 │ ├─controller 控制器目录 │ ├─model 模型目录 │ ├─ ... 更多类库目录 │ │ │ ├─common.php 公共函数文件 │ └─event.ph…

STM32MP157D-DK1 STM32CubeID使用与M核开发

STM32MP157具有A7内核核M4内核&#xff0c;前面介绍的一些文章&#xff0c;都是在A7内核上进行的&#xff0c;本篇来介绍M4内核的开发&#xff0c;以及开发时要用到的STM32 CubeIDE软件的使用。 1 STM32 CubeIDE创建LED工程 STM32CubeIDE是一体式多操作系统开发工具&#xff…

Python 全栈体系【四阶】(十一)

第四章 机器学习 机器学习&#xff1a; 传统的机器学习&#xff1a;以算法为核心深度学习&#xff1a;以数据和计算为核心 感知机 perceptron&#xff08;人工神经元&#xff09; 可以做简单的分类任务掀起了第一波 AI 浪潮 感知机不能解决线性不可分问题&#xff0c;浪潮…

Vue3.x+Echarts (可视化界面)

Vue3.0Echarts &#xff08;可视化界面&#xff09; 1. 简介1.1 技术选型1.2 ECharts支持的数据格式1.3 ECharts使用步骤 2. ECharts图形2.1 通用配置2.2 柱状图2.3 折线图2.4 散点图2.5 直角坐标系常用配置2.6 饼图2.7 地图2.8 雷达图2.9 仪表盘2.10 小结 3. Vue3.2ECharts5数…