草庐IT

【迎战蓝桥】 算法·每日一题(今日详解)-- day6

爱干饭的猿 2023-12-19 原文

🤞目录🤞

💖1. 包含min函数的栈

💖2. 栈的压入、弹出序列

💖3. 从上往下打印二叉树

💖4. 二叉搜索树的后序遍历序列


【大家好,我是爱干饭的猿,如果喜欢这篇文章,点个赞👍,关注一下吧,后续会一直分享题目与算法思路


🌳1. 包含min函数的栈

描述

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。

此栈包含的方法有:

push(value):将value压入栈中

pop():弹出栈顶元素

top():获取栈顶元素

min():获取栈中最小元素

解题思路:

🎈1. 思路一:看到题目时,我们可以简单的想到设置一个min变量储存最小值,每当入数据栈元素小于min时,更新min即可。

🎈2. 思路二:但是思路一我们只能得到数据栈中的最小值,假若面试官要求我们求数据栈中第二小值和第三小值,此方法就行不通了。因此我们可以设置一个辅助栈,辅助栈中的元素个数和数据栈个数相同,只是辅助栈每次存入的是当前已存入数据栈中的最小值,这样如果要求数据栈中第二小值,可以同时让数据栈data_stack和辅助栈min_stack先出栈一个元素,然后return min_stack.peek即可得到数据栈中第二小的值。

🍤思路二:代码如下: 

import java.util.Stack;
public class TwoStackIncludeMin_17 {
    // 数据栈(存入栈元素)
    Stack<Integer> data_stack = new Stack<>();
    // 辅助栈(存入当前数据栈中元素最小值)
    Stack<Integer> min_stack = new Stack<>();
    
    public void push(int node) {
        // 先将node存入数据栈
        data_stack.push(node);
        
        // 判断辅助栈是否为空
        if(min_stack.isEmpty()){
            // 如果辅助栈为空,直接将node存入辅助栈
            min_stack.push(node);
        }else {
            // 如果辅助栈不为空,先将node和辅助栈的栈顶元素做比较
            // 将小的元素存入辅助栈
            if(min_stack.peek() <= node){
                // 辅助栈的栈顶元素更小
                min_stack.push(min_stack.peek());
            }else {
                // node 更小
                min_stack.push(node);
            }
        }
    }

    public void pop() {
        // 数据栈和辅助栈同时出栈,保证两栈元素个数一致
        data_stack.pop();
        min_stack.pop();
    }

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

    // 当期数据栈中最小元素就是辅助栈的栈顶元素
    public int min() {
        return min_stack.peek();
    }
}

🌳2. 栈的压入、弹出序列

描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

1. 0<=pushV.length == popV.length <=1000

2. -1000<=pushV[i]<=1000

3. pushV 的所有数字均不相同

解题思路:

🎈1. 思路一:我们知道可以根据第二个序列也就是出栈顺序,能够得到指定的入栈顺序

(如例题中,第二个序列第一个数为4,入栈时肯定先入栈1,2,3,4,然后才能将4出栈;第二个序列第二个数为5,所以入栈时再将5入栈,然后才能将5出栈,继而将3出栈,2出栈,1出栈)

因此,我们可以遍历第一个序列和第二个序列,当第二个序列元素不等于入栈元素时,继续将第一个序列元素入栈;当第二个序列元素等于入栈元素时,弹出栈顶元素

如此一直循环,当第一个序列元素全部入栈后,退出循环,判断此时栈是否为空,如果栈为空,说明第二个序列元素将栈中元素全部弹出,第二个序列就是是为该栈的弹出顺序。

 🍤思路一:代码如下: 

import java.util.Stack;
public class IsPopOrder_18 {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        // 当第一序列或第二序列为空时,直接返回false
        if(pushA == null || popA == null || pushA.length ==0 || popA.length == 0){
            return false;
        }

        Stack<Integer> stack = new Stack<>();
        int i = 0;
        int j = 0;
        for (;i < pushA.length ; i++) {
            // 将第一序列元素入栈
            stack.push(pushA[i]);
            // 当第二个序列元素等于入栈元素时,弹出栈顶元素
            while (!stack.isEmpty() && stack.peek() == popA[j]){
                stack.pop();
                j++;
            }
        }
        // 如果符合要求,最后栈结构一定是空的
        return stack.isEmpty();
    }
}

🌳3. 从上往下打印二叉树

描述

不分行从上往下打印出二叉树的每个节点,同层节点从左至右打印。例如输入{8,6,10,#,#,2,1},如以下图中的示例二叉树,则依次打印8,6,10,2,1(空节点不打印,跳过),请你将打印的结果存放到一个数组里面。

解题思路:

🎈1. 思路一:本质是层序遍历二叉树,借助队列queue完成。先将根节点存入队列中,然后进入while循环,将队首元素出队并存入list数组中,然后将该队首节点右孩子入队,再将该队首节点左孩子入队。当队列为空时退出循环,list数组中即层序遍历结果。

🍤思路一:代码如下:  

public class PrintFromTopToBottom_19 {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        if(root == null){
            return new ArrayList<>();
        }
        // 创建list数组
        ArrayList<Integer> list = new ArrayList<>();
        // 创建queue队列
        Queue<TreeNode> queue = new LinkedList<>();

        // 先将根节点入队
        queue.offer(root);
        // 当队列不为空时
        while (!queue.isEmpty()){
            // 队首元素出队并存入list数组中
            TreeNode node = queue.poll();
            list.add(node.val);

            if(node.left != null){
                // 将该队首节点右孩子入队
                queue.offer(node.left);
            }
            if(node.right != null){
                // 将该队首节点左孩子入队
                queue.offer(node.right);
            }
        }
        return list;
    }
}

🌳4. 二叉搜索树的后序遍历序列

描述

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回 true ,否则返回 false 。假设输入的数组的任意两个数字都互不相同。

提示:

1.二叉搜索树是指父亲节点大于左子树中的全部节点,但是小于右子树中的全部节点的树。

2.该题我们约定空树不是二叉搜索树

3.后序遍历是指按照 “左子树-右子树-根节点” 的顺序遍历

4.参考下面的二叉搜索树,示例 1

解题思路:

🎈1. 思路一:首先我们应该知道,二叉搜索树性质:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值

后序遍历:左右根方式遍历

所以我们判断依据如下:二叉搜索树 BST的后序序列的合法序列是:对于一个序列 S ,最后一个元素是 x (也就是 root 节点),如果去掉最后一个元素x的序列为 T,那么 T 满足: T 可以分成两段,前一段(x的左子树)节点值都小于 x ,后一段(x的右子树)节点值大于 x 且这两段(子树)都是合法的后序序列 ;当后一段(x的 右子树)出现节点小于x时,说明不是合法的后序序列,return false 即可。

 🍤思路一:代码如下:  

public class VerifySquenceOfBST_20 {
    public boolean VerifySquenceOfBST(int [] sequence) {
        // 序列为空时,直接return false
        if(sequence == null || sequence.length == 0){
            return false;
        }

        return VerifySquenceOfBSTHelper(sequence,0,sequence.length-1);
    }

    private boolean VerifySquenceOfBSTHelper(int[] sequence, int start, int end) {
        // 当子序列首索引大于等于尾索引,说明子序列都是合法后序序列,判断完毕,return true
        if(start >= end){
            return true;
        }
        // 得到当前子序列首索引
        int i = start;
        // 找到子序列中后一段(x的右子树)第一个大于root节点的位置
        while(i < end && sequence[i] < sequence[end]){
            i++;
        }
        // 遍历子序列中后一段(x的右子树)节点
        for (int j = i; j < end; j++) {
            // 当后一段(x的右子树)出现节点小于x时,说明不是合法的后序序列,return false
            if(sequence[j] < sequence[end]){
                return false;
            }
        }
        // 递归判断当前序列的前一段和后一段是否是合法的后序序列
        return VerifySquenceOfBSTHelper(sequence,start,i-1) && VerifySquenceOfBSTHelper(sequence,i,end-1);
    }
}

有关【迎战蓝桥】 算法·每日一题(今日详解)-- day6的更多相关文章

  1. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

  2. ruby-on-rails - rails : Find tasks that were created on a certain day? - 2

    我有一个任务列表(名称、starts_at),我试图在每日View中显示它们(就像iCal)。deftodays_tasks(day)Task.find(:all,:conditions=>["starts_atbetween?and?",day.beginning,day.ending]end我不知道如何将Time.now(例如“2009-04-1210:00:00”)动态转换为一天的开始(和结束),以便进行比较。 最佳答案 deftodays_tasks(now=Time.now)Task.find(:all,:conditio

  3. 100个python算法超详细讲解:画直线 - 2

    1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva

  4. 蓝桥杯备赛(二) - 2

    目录前言: 一、ASC分析代码实现二、 卡片分析代码实现三、 直线分析代码实现四、货物摆放分析代码实现小结:前言:  在刷题的过程中,发现蓝桥杯的题目和力扣的差别很大。让人有一种不一样的感觉,蓝桥杯题目偏向对于实际问题用编程去的解决,而力扣给人感觉很锻炼自己的编程思维,逻辑能力。两者结合去刷,相信会有不一样的收获。 一、ASC  已知大写字母A的ASCII码为65,请问大写字母L的ASCII码是多少?分析  这道题目看上去很简单,我们需确定自己计算的准确,所以我建议用编程去解决。代码实现publicclassTest8{publicstaticvoidmain(String[]args){Sy

  5. 物联网MQTT协议详解 - 2

    一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su

  6. 什么是0day漏洞?如何预防0day攻击? - 2

    什么是0day漏洞?0day漏洞,是指已经被发现,但是还未被公开,同时官方还没有相关补丁的漏洞;通俗的讲,就是除了黑客,没人知道他的存在,其往往具有很大的突发性、破坏性、致命性。0day漏洞之所以称为0day,正是因为其补丁永远晚于攻击。所以攻击者利用0day漏洞攻击的成功率极高,往往可以达到目的并全身而退,而防守方却一无所知,只有在漏洞公布之后,才后知后觉,却为时已晚。“后知后觉、反应迟钝”就是当前安全防护面对0day攻击的真实写照!为了方便大家理解,中科三方为大家梳理当前安全防护模式下,一个漏洞从发现到解决的三个时间节点:T0:此时漏洞即0day漏洞,是已经被发现,还未被公开,官方还没有相

  7. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  8. ruby - 在 Ruby 中实现 Luhn 算法 - 2

    我一直在尝试用Ruby实现Luhn算法。我一直在执行以下步骤:该公式根据其包含的校验位验证数字,该校验位通常附加到部分帐号以生成完整帐号。此帐号必须通过以下测试:从最右边的校验位开始向左移动,每第二个数字的值加倍。将乘积的数字(例如,10=1+0=1、14=1+4=5)与原始数字的未加倍数字相加。如果总模10等于0(如果总和以零结尾),则根据Luhn公式该数字有效;否则无效。http://en.wikipedia.org/wiki/Luhn_algorithm这是我想出的:defvalidCreditCard(cardNumber)sum=0nums=cardNumber.to_s.s

  9. Ruby 斐波那契算法 - 2

    下面是我写的一个计算斐波那契数列中的值的方法:deffib(n)ifn==0return0endifn==1return1endifn>=2returnfib(n-1)+(fib(n-2))endend它工作到n=14,但在那之后我收到一条消息说程序响应时间太长(我正在使用repl.it)。有人知道为什么会这样吗? 最佳答案 Naivefibonacci进行了大量的重复计算-在fib(14)fib(4)中计算了很多次。您可以将内存添加到您的算法中以使其更快:deffib(n,memo={})ifn==0||n==1returnnen

  10. ruby - Rails 比较 date.end_of_day.to_datetime 和 date.to_datetime.end_of_day 返回的日期对象值时返回 false - 2

    ruby1.9.3dev(2011-09-23修订版33323)[i686-linux]轨道3.0.20最近为什么在与DateTimeonRails相关的RSpecs项目上工作我发现在给定日期以下语句发出的值date.end_of_day.to_datetime和date.to_datetime.end_of_day虽然它们表示相同的日期时间,但比较时返回false。为了确认这一点,我打开了Rails控制台并尝试了以下操作1.9.3dev:053>monday=Time.now.monday=>2013-02-2500:00:00+05301.9.3dev:054>monday.cla

随机推荐