LeetCode(2)

目录

概念解释

 队列

树的概念 

 结点的分类

有序树

无序树

森林 

二叉树

满二叉树

完全二叉树

 二叉排序树

平衡二叉树 

1.用栈实现队列

解法:双栈 

 2.字符串解码

 解法:栈

3.二叉树的中序遍历

 解法一:递归

解法二:迭代 

4.二叉树的前序遍历 

解法一:递归

 解法二:迭代

5.二叉树的后序遍历

 6.平衡二叉树

自底向上的递归 

7.二叉树的最大深度

 解法一:迭代

解法二:递归 

8.对称二叉树

解法一:递归 

解法二:迭代 


概念解释

栈(堆栈) : 后进先出的结构,Last In First Out,简称LIFO结构。

 队列

先进先出的结构,First In First Out,简称FIFO结构。

树(Tree)是n(n >= 0)个结点的有限集合,当n=0时,称为空树。

在任意一个非空树中应满足:

        1.有且仅有一个特定的称为根(Root)的结点。

        2.当n>1时,其余节点可分成m(m>0)个互不相交的有限集合T1,T2,...Tm,其中每个集合本身又是一棵树,并且称为根结点的子树(SubTree)。

树的概念 

结点的度:结点拥有的子树的数量;

结点的深度(层次):从上往下数,结点距离根结点的距离。

结点的高度:从下往上数,结点在第几层,结点的高度就是多少;

树的高度:结点深度最大的那个结点的深度就是树的深度;

树的度:树中度最大结点的度就是树的度。

 结点的分类

叶子节点:度为0的结点;

分支结点(内部结点):度不为0的结点(除根节点)。

有序树

从逻辑上看,树中结点的各子树从左至右是有次序的,不能互换。

无序树

从逻辑上看,树中结点的各子树从左至右是无次序的,可以互换。

森林 

m(m>=0)棵互不相交的树的集合。

二叉树

二叉树是n(n>=0)个结点的有限集合;

可以是空二叉树,即n=0;

可以是由一个根节点和两个互不相交的树(被称为根的左子树和右子树)组成。

左子树和右子树又分别是一课二叉树。、

特点:每个结点最多只有两棵子树;

           左右子树不能颠倒(二叉树是有序树)

满二叉树

每层结点的个数都达到最大值;即如果一个二叉树的层数为k,并且总结点数位2^{k}-1,那么这个数就是满二叉树。

特点:1.最后一层都是叶子节点;

           2.不存在度为1的结点;

           3.按层序从1开始编号,结点i的左孩子为2i,右孩子为2i+1;

               结点i的父结点为i/2向下取整。

完全二叉树

当且仅当其每个结点都与满二叉树中编号位1-n的结点一一对应时,称为完全二叉树。

即,相比于满二叉树,完全二叉树少一个右下角。

特点:1.只有最后两层可能又叶子结点;

           2.最多只有一个度为1的结点;

           3.按层序从1开始编号,结点i的左孩子为2i,右孩子为2i+1;

               结点i的父结点为i/2向下取整。

           4.如果一个完全二叉树的有n个结点,那么,当结点的编号i<=n/2向下取整,那么这些结点为分支结点;当结点的编号i>n/2向下取整,那么这些结点为叶子结点;

 二叉排序树

左子树上所有结点的关键字均小于根节点的关键字,右子树上所有结点的关键字均大于根节点的关键字;左子树和右子树又各是一棵二叉排序树。

平衡二叉树 

树上任一结点的左子树和右子树的深度之差不超过1.

1.用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可

进阶:

  • 你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。

解法:双栈 

利用双栈就可以实现队列,一个做输入栈,一个做输出栈。

队列是先进先出,栈刚好相反,但如果,先把数据压入输入栈,再从输入栈将数据压入输出栈,就和队列一样了。

class MyQueue {private static Stack<Integer> inStack;private static Stack<Integer> outStack;public MyQueue() {inStack = new Stack<Integer>();outStack = new Stack<Integer>();}public void push(int x) {inStack.push(x);}public int pop() {if(outStack.isEmpty()){inToOut();}return outStack.pop();}private void inToOut(){//如果输入栈非空,将输入栈的元素弹出,然后压入输出栈while(!inStack.isEmpty()){outStack.push(inStack.pop());}}public int peek() {if(outStack.isEmpty()){inToOut();}return outStack.peek();}public boolean empty() {return inStack.isEmpty() && outStack.isEmpty();}
}/*** Your MyQueue object will be instantiated and called as such:* MyQueue obj = new MyQueue();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.peek();* boolean param_4 = obj.empty();*/

 2.字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

 

 解法:栈

 本题考查我们对栈的操作。

以3[a]2[bc]为例,我们从3开始入栈;

如果是数字,将数字进行解析,然后进栈,

如果是 [ 或者 字母,直接进栈,

如果是 ] ,开始出栈,直到遇到 [ 为止。

class Solution {public String decodeString(String s) {//存数字的栈Stack<Integer> countStack = new Stack<>();//存字母或 [ ] 的栈Stack<String> resStack = new Stack<>();//初始下标int index = 0;int len = s.length();String res = "";while(index < len){char ch = s.charAt(index);//处理数字if(Character.isDigit(ch)){StringBuffer sb = new StringBuffer();//如果是数字,就加到sb中while(Character.isDigit(s.charAt(index))){sb.append(s.charAt(index++));}countStack.push(Integer.parseInt(sb.toString()));}else if(ch == '['){//当ch为[ 时,让res入栈,将res置空resStack.push(res);res = "";index++;}else if(ch == ']'){//当ch为]时,开始出栈StringBuffer temp = new StringBuffer(resStack.pop());int repeaTims = countStack.pop();for(int i = 0;i<repeaTims;i++){temp.append(res);}res = temp.toString();index++;}else{//当ch为字母时,拼接到res后面res += s.charAt(index++);}}return res;}
}

3.二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

进阶: 递归算法很简单,你可以通过迭代算法完成吗? 

 解法一:递归

 首先,我们要知道二叉树的中序遍历是什么,根节点-左子树-右子树,而且在访问左子树或右子树时,还是同样的方式,直到整个树遍历完,终止条件就是当结点为空时,中止。

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();accessTree(root,res);return res;}public void accessTree(TreeNode root,List<Integer> res){if(root == null){return;}accessTree(root.left,res);res.add(root.val);accessTree(root.right,res);}
}

时间复杂度:O(n)
空间复杂度:O(n)

解法二:迭代 

 题目要求使用迭代。

首先,我们要明确中序遍历的步骤:左、根、右;所以先访问左子树,但是根节点的值需要保存下来,因为我们为了效率,必须保证每个结点只访问了一次。

我们引入一个栈用来保存根节点。

迭代步骤:先将根节点压入栈,然后访问左子树,如果左子树不为空,继续将左子树的根节点压入栈,如果左子树为空,将其弹出栈然后输出,在访问右子树,直到整个树遍历完。

public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();while(root != null || !stack.isEmpty()){while(root!=null){stack.push(root);root = root.left;}root = stack.pop();res.add(root.val);root = root.right;}return res;}

时间复杂度:O(n)
空间复杂度:O(n) 

4.二叉树的前序遍历 

 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

 和中序遍历思路一样。

要注意的是遍历顺序:根节点、左子树、右子树

解法一:递归

public List<Integer> preorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();accessTree(root,res);return res;}public void accessTree(TreeNode root,List<Integer> res){//终止条件if(root==null){return;}//先访问根节点res.add(root.val);//左子树accessTree(root.left,res);//右子树accessTree(root.right,res);}

  时间复杂度:O(n)
空间复杂度:O(n)

 解法二:迭代

public List<Integer> preorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();while(root!=null || !stack.isEmpty()){while(root!=null){res.add(root.val);stack.push(root);root = root.left;}root =  stack.pop();root = root.right;}return res;}

时间复杂度:O(n)
空间复杂度:O(n)  

5.二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 

进阶:递归算法很简单,你可以通过迭代算法完成吗?

递归跟前两个思路一样,但是迭代就差很多,这是因为后序遍历的步骤是左子树、右子树、根节点,每次需要遍历右子树时,都需要借助根结点,所以这里需要定义一个空结点,每次都要保存根节点。

class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<Integer>();if (root == null) {return res;}Deque<TreeNode> stack = new LinkedList<TreeNode>();TreeNode prev = null;while (root != null || !stack.isEmpty()) {while (root != null) {stack.push(root);root = root.left;}root = stack.pop();if (root.right == null || root.right == prev) {res.add(root.val);prev = root;root = null;} else {stack.push(root);root = root.right;}}return res;}
}

 6.平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

自底向上的递归 

public boolean isBalanced(TreeNode root) {return height(root) != -1;}public int height(TreeNode root){if(root == null){return 0;}//从左子树开始判断int leftH = height(root.left);int rightH = height(root.right);if(leftH == -1 || rightH == -1 || (leftH-rightH) > 1||(rightH-leftH)>1){return -1;}return leftH > rightH ? (leftH + 1):(rightH + 1);}

7.二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

 解法一:迭代

使用队列里存放当前层的所有节点。每次拓展下一层的时候,我们需要将队列里的所有节点都拿出来进行拓展,这样能保证每次拓展完的时候队列里存放的是当前层的所有节点,即我们是一层一层地进行拓展,最后我们用一个变量 ans\textit{ans}ans 来维护拓展的次数,

public int maxDepth(TreeNode root) {if(root == null){return 0;}Queue<TreeNode> q = new LinkedList<>();int count = 0;q.offer(root);while(!q.isEmpty()){int size = q.size();while(size>0){TreeNode n = q.poll();if(n.left != null){q.offer(n.left);}if(n.right!=null){q.offer(n.right);}size--;}count++;}return count;}

解法二:递归 

如果我们知道了左子树和右子树的最大深度 l和 r,那么该二叉树的最大深度即为

max⁡(l,r)+1.
而左子树和右子树的最大深度又可以以同样的方式进行计算。

public int maxDepth(TreeNode root) {if(root == null){return 0;}int l = maxDepth(root.left);int r = maxDepth(root.right);return l > r ? l + 1 : r +1;}

8.对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

 

解法一:递归 

乍一看使用递归很好解决。
根据题目的描述,镜像对称,就是左右两边相等,也就是左子树和右子树是相当的。
注意这句话,左子树和右子相等,也就是说要递归的比较左子树和右子树。

class Solution {public boolean isSymmetric(TreeNode root) {if(root==null) {return true;}return dfs(root.left,root.right);}boolean dfs(TreeNode left, TreeNode right) {if(left==null && right==null) {return true;}if(left==null || right==null) {return false;}if(left.val!=right.val) {return false;}return dfs(left.left,right.right) && dfs(left.right,right.left);}
}

解法二:迭代 

首先我们引入一个队列。初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。

class Solution {public boolean isSymmetric(TreeNode root) {return check(root, root);}public boolean check(TreeNode u, TreeNode v) {Queue<TreeNode> q = new LinkedList<TreeNode>();q.offer(u);q.offer(v);while (!q.isEmpty()) {u = q.poll();v = q.poll();if (u == null && v == null) {continue;}if ((u == null || v == null) || (u.val != v.val)) {return false;}q.offer(u.left);q.offer(v.right);q.offer(u.right);q.offer(v.left);}return true;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云微呼探索人工智能机器人对话:过去、现在和未来

随着科技的迅速发展&#xff0c;人工智能&#xff08;AI&#xff09;机器人已经成为我们日常生活中的重要一部分。从简单的语音助手到能够进行复杂对话的智能机器人&#xff0c;AI技术正在改变着我们与机器之间的互动方式。本文将探讨人工智能机器人对话的历史、现状以及未来发…

[SwiftUI]系统弹窗和自定义弹窗

一、系统弹窗 在 SwiftUI 中&#xff0c;.alert 是一个修饰符&#xff0c;用于在某些条件下显示一个警告对话框。Alert 可以配置标题、消息和一系列的按钮。每个按钮可以是默认样式、取消样式&#xff0c;或者是破坏性的样式&#xff0c;它们分别对应不同的用户操作。 1.Aler…

前端qrcode生成二维码详解

文章目录 前言1、浏览器支持2、优点3、缺点4、相关方法5、安装及使用示例 前言 qrcode 是一个基于JavaScript的二维码生成库&#xff0c;主要是通过获取 DOM 的标签&#xff0c;再通过 HTML5 Canvas 绘制而成&#xff0c;不依赖任何库。 官方文档&#xff1a;https://www.npm…

Kafka-服务端-GroupCoordinator

在每一个Broker上都会实例化一个GroupCoordinator对象&#xff0c;Kafka按照Consumer Group的名称将其分配给对应的GroupCoordinator进行管理&#xff1b; 每个GroupCoordinator只负责管理Consumer Group的一个子集&#xff0c;而非集群中全部的Consumer Group。 请注意与Kaf…

Java项目:基于SSM框架实现的企业员工岗前培训管理系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm821基于ssm框架实现的企业员工岗前培训管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格…

NetExec:一款功能强大的自动化网络安全评估与漏洞测试工具

关于NetExec NetExec是一款功能强大的自动化网络安全评估与漏洞测试工具&#xff0c;该工具可以帮助广大研究人员以自动化的形式测试大型网络的安全&#xff0c;并通过利用网络服务漏洞来评估目标网络的安全态势。 支持的协议 1、SMB协议 2、LDAP协议 3、WinRM协议 4、MSSQL协…

go语言函数进阶

1.变量作用域 全局变量 全局变量是定义在函数外部的变量&#xff0c;它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。 package mainimport "fmt"//定义全局变量num var num int64 10func testGlobalVar() {fmt.Printf("num%d\n", num) /…

vue-head 插件设置浏览器顶部 favicon 图标 - 动态管理 html 文档头部标签内容

目录 需求实现11. 安装插件2. 项目内 main.js 引入3. vue页面使用 实现2其他 需求 vue项目中浏览器页面顶部图标可配置 实现1 使用 vue-head 插件实现 vue-head 插件可实现 html 文档中 head 标签中的内容动态配置&#xff08;npm 官网 vue-head 插件&#xff09; 1. 安装插件 …

promethues基础概念

promethues是一个开源的系统监控以及报警系统&#xff0c;整个zabbix的功能&#xff0c;系统&#xff0c;网络&#xff0c;设备 promethues可以兼容网络和设置被&#xff0c;容器监控&#xff0c;告警系统&#xff0c;因为他和k8s是一个项目基金开发的产品&#xff0c;天生匹配…

代码随想录算法训练营第34天 | 1005.K次取反后最大化的数组和 134.加油站 135.分发糖果

K次取反后最大化的数组和 贪心局部最优&#xff1a;将绝对值大的负数变为正数&#xff0c;当前和变为最大&#xff1b;全局最优&#xff1a;整体获得最大和。 如果负数都变成正数之后&#xff0c;k > 0&#xff0c;仍然需要继续翻转&#xff0c;贪心局部最优&#xff1a;将最…

14.STM32F4 LCD屏幕概念及源码下载(LCD之一)

一、LCD液晶显示屏介绍 1、常见的显示设备 在目前市面上&#xff0c;常见的显示设备种类有&#xff1a;LED、显示数码管、点阵LED显示屏、LCD液晶显示屏&#xff0c;这几种设备的特点是&#xff1a; &#xff08;1&#xff09;LED LED灯是最简单的显示设备&#xff0c;它只有两…

天拓四方:物联网网关在机械制造企业的应用

随着物联网技术的不断发展&#xff0c;越来越多的机械制造企业开始探索如何利用物联网技术提升生产效率、降低运营成本。物联网网关作为物联网架构中的关键设备&#xff0c;能够实现设备间的数据交互与远程控制&#xff0c;为机械制造企业带来了巨大的商业价值。它能够实现设备…

漏洞原理XSS存贮型漏洞

漏洞原理XSS存贮型漏洞 XSS&#xff08;跨站脚本攻击&#xff09;是一种常见的Web安全漏洞&#xff0c;它允许攻击者将恶意代码注入到网页中&#xff0c;进而攻击用户的浏览器。存储型XSS漏洞是一种特定类型的XSS漏洞&#xff0c;它发生在Web应用程序中&#xff0c;其中用户输入…

小红叒战小紫

概率dp #include <iostream> #include <string> #include <stack> #include <vector> #include <queue> #include <deque> #include <set> #include <map> #include <unordered_map> #include <unordered_set> #…

在租户内启用SharePoint Embedded

要开启 SharePoint Embedded&#xff0c;你得是管理员&#xff0c;然后按照这些步骤操作&#xff1a; 登录到你的 SharePoint 管理中心。在左边的菜单里找到“设置”选项&#xff0c;点进去。 3. 在设置页面里找到“SharePoint Embedded 应用”。 4.如果这个功能还没开启&…

Android Settings 显示电池点亮百分比

如题&#xff0c;Android 原生 Settings 里有个 电池电量百分比 的选项&#xff0c;打开后电池电量百分比会显示在状态栏。 基于 Android 13 &#xff0c; 代码在 ./packages/apps/Settings/src/com/android/settings/display/BatteryPercentagePreferenceController.java &am…

【flutter项目类型】project type如何区分

通过项目中.metadata内容区分 如 # Used by Flutter tool to assess capabilities and perform upgrades etc. # # This file should be version controlled and should not be manually edited.version:revision: 85684f9300908116a78138ea4c6036c35c9a1236channel: stablep…

【大数据】Flink 架构(二):数据传输

《Flink 架构》系列&#xff08;已完结&#xff09;&#xff0c;共包含以下 6 篇文章&#xff1a; Flink 架构&#xff08;一&#xff09;&#xff1a;系统架构Flink 架构&#xff08;二&#xff09;&#xff1a;数据传输Flink 架构&#xff08;三&#xff09;&#xff1a;事件…

(Aliexpress)速卖通卖家通过自养号补单提高出单率

在跨境电商领域&#xff0c;有些卖家可能会遇到这样的问题&#xff1a;自己的速卖通店铺始终没有订单产生。那么&#xff0c;当速卖通店铺一直不出单时&#xff0c;我们应该如何进行补救呢&#xff1f;今天珑哥将围绕这个问题展开探讨&#xff0c;并分享一些提升速卖通店铺销量…

HCIP复习课(mpls实验)

1、IP配置&#xff1a; R1&#xff1a; R2&#xff1a; R3&#xff1a; R4&#xff1a; R5&#xff1a; R6&#xff1a; R7&#xff1a; R8&#xff1a; 2、rip&#xff0c;ospf配置&#xff1a; R2&#xff1a; R3&#xff1a; R4&#xff1a; R5&#xff1a; R6&#xff1a…