LeetCode 394, 61, 100

目录

  • 394. 字符串解码
    • 题目链接
    • 标签
    • 思路
    • 代码
  • 61. 旋转链表
    • 题目链接
    • 标签
    • 思路
    • 代码
  • 100. 相同的树
    • 题目链接
    • 标签
    • 思路
    • 代码
      • 递归版前序遍历
      • 层序遍历

394. 字符串解码

题目链接

394. 字符串解码

标签

栈 递归 字符串

思路

本题可以使用两个栈来解决,一个栈 timesStack 存储字符串重复的次数,另一个栈 stringStack 存储字符串的前缀。针对字符不同,有如下四种操作:

  • 如果字符是数字,则将其记录到一个外部变量 times 中,从而计算重复次数。
  • 如果字符是小写字母,则将其拼接到一个外部变量 builder 中。
  • 如果字符是 '[',则将 timesbuilder.toString() 分别放到 timesStackstringStack 中,为了 timesbuilder 还能正常使用,将其清空:times 置为 0,builder 换成新的 new StringBuilder()
  • 如果字符是 ']',则将 stringStack 栈顶的字符串 (使用完就没用了,记得弹栈) 作为前缀 prefixtimesStack 栈顶的次数 (使用完就没用了,记得弹栈) 作为重复次数 timesbuilder.toString() 作为待重复的字符串 str,构成一个字符串,并将其作为构造新 StringBuilder 的参数构造一个新的 StringBuilderbuilder

下图针对 '[', ']' 这两个字符进行了示例:
alt text

代码

class Solution {public String decodeString(String s) {LinkedList<Integer> timesStack = new LinkedList<>(); // 存储 重复次数 的栈LinkedList<String> prefixStack = new LinkedList<>(); // 储存 字符串前缀 的栈int times = 0; // 当前字符串的重复次数StringBuilder builder = new StringBuilder(); // 拼接当前字符串for (char ch : s.toCharArray()) {if (ch >= '0' && ch <= '9') { // ch 是数字times = times * 10 + (ch - '0'); // 计算多位数} else if (ch == '[') {timesStack.push(times);prefixStack.push(builder.toString());// 为了能够继续使用 times 和 builder,进行清空操作times = 0;builder = new StringBuilder();} else if (ch == ']') {String prefix = prefixStack.pop();String str = builder.toString();int repeatTimes = timesStack.pop();builder = new StringBuilder(joint(prefix, str, repeatTimes));} else { // ch 是小写字母builder.append(ch);}}return builder.toString();}// 以 prefix 为前缀,将 str 重复 times 次,将得到的字符串返回private String joint(String prefix, String str, int times) {StringBuilder builder = new StringBuilder(prefix);while (times-- > 0) {builder.append(str);}return builder.toString();}
}

61. 旋转链表

题目链接

61. 旋转链表

标签

链表 双指针

思路

本题的做法十分巧妙:将链表向右移动可以分为五步:

  1. 统计链表的节点个数。
  2. 计算头节点右移的次数:头节点右移的次数为 链表节点个数 减去 k,为了减少移动的次数(避免绕环多周),在 k 运算之前,先对链表节点个数进行取余。
  3. 将链表头尾相连,形成 环形链表
  4. 在环形链表中将头节点右移指定次数,获取新的头节点。
  5. 断开 新的尾节点 和 新的头节点 之间的 联系,返回新的头节点。

使用示例1的 head = [1,2,3,4,5], k = 2 进行举例,则会有如下的流程 (此时指定移动 5 - 2 = 3 次):
alt text

具体细节请看代码:

代码

class Solution {public ListNode rotateRight(ListNode head, int k) {// 如果 不需要移动 或 链表为空 或 链表只有一个节点if (k == 0 || head == null || head.next == null) {return head; // 则直接返回 head}// 统计链表的节点个数,最终 curr 是链表的尾节点int n = 1;ListNode curr = head;while (curr.next != null) {curr = curr.next;n++;}// 计算头节点右移的次数int times = n - (k % n);if (times == n) { // 如果 头节点右移的次数 与 链表的节点数 相同return head; // 则直接返回头节点,不需要移动}curr.next = head; // 让链表的尾节点指向头节点,从而形成循环链表while (times-- > 0) { // 右移 times 次curr = curr.next;}// curr 是新链表的尾节点,新的头节点是 curr 的下一个节点ListNode newHead = curr.next; // 获取新的头节点curr.next = null; // 将链表从新的 尾节点 和 头节点处 剪断return newHead;}
}

100. 相同的树

题目链接

100. 相同的树

标签

树 深度优先搜索 广度优先搜索 二叉树

思路

本题和 101. 对称二叉树 很像,不过本题只是简单考察 二叉树的遍历,并且本题检查两颗二叉树,而101题只检查一颗二叉树,并且稍微难一点。

既然本题考查 二叉树的遍历,那么无论是使用深度优先搜索的三种遍历方式(前序遍历、中序遍历、后序遍历),还是使用广度优先搜索的遍历方式——层序遍历,都可以。

代码

递归版前序遍历

以下代码是递归版的前序遍历:先对本节点的值进行判断,然后遍历左子树,最后遍历右子树

class Solution {public boolean isSameTree(TreeNode p, TreeNode q) {if (p == null && q == null) { // 如果 p, q 都是 nullreturn true; // 则返回 true} else if (p == null || q == null) { // 此时 p, q 只有一个是 nullreturn false; // 则返回 false} else if (p.val != q.val) { // 如果 p, q 的值不同return false; // 则返回 false}return isSameTree(p.left, q.left) // 判断 p 和 q 的 左子树 是否完全一致&& isSameTree(p.right, q.right); // 判断 p 和 q 的 右子树 是否完全一致}
}

层序遍历

class Solution {public boolean isSameTree(TreeNode p, TreeNode q) {if (p == null && q == null) { // 如果 p, q 都是 nullreturn true; // 则返回 true} else if (p == null || q == null) { // 此时 p, q 只有一个是 nullreturn false; // 则返回 false}LinkedList<TreeNode> queueP = new LinkedList<>(); // 用于遍历二叉树 pLinkedList<TreeNode> queueQ = new LinkedList<>(); // 用于遍历二叉树 qqueueP.offer(p); // 先将头节点放入队列queueQ.offer(q); // 先将头节点放入队列while (!queueP.isEmpty() && !queueQ.isEmpty()) {TreeNode nodeP = queueP.poll(); // 取出 p 中的一个节点TreeNode nodeQ = queueQ.poll(); // 取出 q 中的一个节点if (nodeP.val != nodeQ.val) { // 如果它们的值不同return false; // 则返回 false}TreeNode leftP = nodeP.left, rightP = nodeP.right; // 获取 nodeP 的左右子节点TreeNode leftQ = nodeQ.left, rightQ = nodeQ.right; // 获取 nodeQ 的左右子节点// 可以使用 leftP == null ^ leftQ == null 作为判断条件,它与以下条件等价if ((leftP == null && leftQ != null)|| (leftP != null && leftQ == null)) { // 如果对应的节点只有一个为nullreturn false; // 则返回 false}// 可以使用 rightP == null ^ rightQ == null 作为判断条件,它与以下条件等价if ((rightP == null && rightQ != null)|| (rightP != null && rightQ == null)) { // 如果对应的节点只有一个为nullreturn false; // 则返回 false}// 经过以上判断,leftP 和 leftQ 如果有一个为 null,则都是 null;否则都有值if (leftP != null) { // 如果有值,则将其添加到队列中等待比较queueP.offer(leftP);queueQ.offer(leftQ);}// 经过以上判断,rightP 和 rightQ 如果有一个为 null,则都是 null;否则都有值if (rightP != null) { // 如果有值,则将其添加到队列中等待比较queueP.offer(rightP);queueQ.offer(rightQ);}}// 如果有一个队列不为空,则两颗二叉树的节点个数不同,只有两个队列同时为空才代表这两颗二叉树完全一致return queueP.isEmpty() && queueQ.isEmpty();}
}

如果只使用 queueP, queueQ 中的一个,就很像对一颗二叉树的层序遍历(一层一层地遍历二叉树)了:

  • 创建队列:LinkedList<TreeNode> queue = new LinkedList<>();
  • 将根节点提前加入队列:queue.offer(root);
  • 在队列不为空的时候进行循环:while (!queue.isEmpty()),以下都是循环中的操作:
    • 获取当前节点:TreeNode curr = queue.poll();
    • 对当前节点进行某种操作。
    • 获取当前节点的左右子节点:TreeNode left = curr.left, right = curr.right;
    • 如果左子节点不为空,则将其加入队列:if (left != null) { queue.offer(left) }
    • 如果右子节点不为空,则将其加入队列:if (right != null) { queue.offer(right) }

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

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

相关文章

开源安全态势感知平台Security Onion

简介 Security Onion是一款由安全防御人员为安全防御人员构建的免费开放平台。它包括网络可见性、主机可见性、入侵检测蜜罐、日志管理和案例管理等功能。详细信息可以查看官网Security Onion Solutions 在网络可见性方面&#xff0c;Security Onion提供了基于签名的检测&…

JAVA:Filer过滤器+案例:请求IP访问限制和请求返回值修改

JAVA&#xff1a;Filer过滤器 介绍 Java中的Filter也被称为过滤器&#xff0c;它是Servlet技术的一部分&#xff0c;用于在web服务器上拦截请求和响应&#xff0c;以检查或转换其内容。 Filter的urlPatterns可以过滤特定地址http的请求&#xff0c;也可以利用Filter对访问请求…

Wireshark抓取HTTP

HTTP请求响应 使用wireshark抓取 本地机器是192.168.33.195&#xff0c;远程机器是192.168.32.129&#xff0c;远程HTTP服务端口是9005 TCP/IP实际共分为4层&#xff0c;抓包信息中可以看到各层的数据&#xff0c;最上面的数据帧包含了所有数据。 附&#xff1a;抓取本地H…

专题四:设计模式总览

前面三篇我们通过从一些零散的例子&#xff0c;和简单应用来模糊的感受了下设计模式在编程中的智慧&#xff0c;从现在开始正式进入设计模式介绍&#xff0c;本篇将从设计模式的7大原则、设计模式的三大类型、与23种设计模式的进行总结&#xff0c;和描述具体意义。 设计模式体…

Docker-compose单机容器集群编排

传统的容器管理&#xff1a;Dockerfile文件 -> 手动执行 docker build 一个个镜像的构建 -> 手动执行 docker run 一个个容器的创建和启动 容器编排管理&#xff1a;Dockerfile文件 -> 在docker-compose.yml配置模板文件里定义容器启动参数和依赖关系 -> 执行dock…

PlantUML-UML 绘图工具安装、Graphviz安装、本地使用/在线使用、语法、图示案例

文章目录 前言本地安装vscode安装插件下载安装Graphviz配置Graphviz环境变量测试 在线使用演示PlantUML语法总结活动图&#xff08;新语法&#xff09;时序图类图用例图其他图 更多相关内容可查看 前言 本篇提供两种使用方式分别为 在线使用地址1&#xff1a;https://www.pla…

在安卓手机上原生运行docker

前言 之前的文章(香橙派5plus上跑云手机方案一 redroid(带硬件加速))在Ubuntu的docker里运行安卓&#xff0c;这里说下怎么在安卓手机下运行docker&#xff0c;测试也可以跑Ubuntu。 想在手机上运行docker想的不是一天两天了&#xff0c;其实很久之前就有这个想法了&#xff…

Docker网络模式和Cgroup资源限制

目录 1、Docker网络 &#xff08;1&#xff09;Docker网络实现原理 查看容器的输出和日志信息 2、Docker 的网络模式 查看docker列表 &#xff08;1&#xff09;网络模式详解 1&#xff09;host模式 2&#xff09;container模式 3&#xff09;none模式 4&#xff09;br…

SpringCloud教程 | 第十篇: 读取Nacos的配置

1、nacos服务器选用 2、test.yaml这一个DataId配置如下&#xff1a; config:name: aabb222 spring:application:name: testdatasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/hmblogs?useUni…

MongoDB教程(十二):MongoDB数据库索引

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、MongoD…

【鸿蒙OS】【ArkUI】鸿蒙OS UI布局适配终极攻略

鸿蒙OS UI布局适配终极攻略 像素适配大法&#xff0c;此方法也适合Android ArkUI为开发者提供4种像素单位&#xff0c;框架采用vp为基准数据单位。 vp相当于Android里的dp fp相当于Android里的sp 官方是如何定义的呢,如下图 今天我来教大家如何用PX做到ArkUI的终级适配&…

Leetcode 2011. 执行操作后的变量值

问题描述&#xff1a; 存在一种仅支持 4 种操作和 1 个变量 X 的编程语言&#xff1a; X 和 X 使变量 X 的值 加 1--X 和 X-- 使变量 X 的值 减 1 最初&#xff0c;X 的值是 0 给你一个字符串数组 operations &#xff0c;这是由操作组成的一个列表&#xff0c;返回执行所有…

C++初学者指南-5.标准库(第一部分)--标准库算法介绍

C初学者指南-5.标准库(第一部分)–标准库算法介绍 文章目录 C初学者指南-5.标准库(第一部分)--标准库算法介绍C的标准算法是&#xff1a;第一个示例组织输入范围自定义可调用参数并行执行(C17)迭代器和范围的类别错误消息命名空间std::ranges中的算法 (C20)算法参数图标相关内容…

linux 安装 RocketMQ 4.7

安装介绍 Centos 7RocketMQ 4.7JDK 1.8 (安装JDK参考)RocketMQ的官网地址&#xff1a; http://rocketmq.apache.orgGithub地址是 https://github.com/apach e/rocketmq 安装操作 下载RocketMQ RocketMQ运行版本下载地址&#xff1a; Rocketmq-all-4.7.1-bin-release.zip …

httpx,一个网络请求的 Python 新宠儿

大家好&#xff01;我是爱摸鱼的小鸿&#xff0c;关注我&#xff0c;收看每期的编程干货。 一个简单的库&#xff0c;也许能够开启我们的智慧之门&#xff0c; 一个普通的方法&#xff0c;也许能在危急时刻挽救我们于水深火热&#xff0c; 一个新颖的思维方式&#xff0c;也许能…

AI大模型新纪元:哪四大趋势引领未来智能革命?

在人工智能热潮持续居高不下背景下&#xff0c;虽然全球AI大模型企业卷参数的激烈程度有所放缓&#xff0c;但大模型仍不断朝着万亿、十万亿参数发展&#xff0c;并推动多模态持续演进以通向AGI。同时&#xff0c;大模型也在朝向轻量化、高效化、垂直多元化发展&#xff0c;进而…

每日复盘-20240718

20240718 六日涨幅最大: ------1--------300713--------- 英可瑞 五日涨幅最大: ------1--------301016--------- 雷尔伟 四日涨幅最大: ------1--------301016--------- 雷尔伟 三日涨幅最大: ------1--------301016--------- 雷尔伟 二日涨幅最大: ------1--------300713----…

Linux LVM扩容方法

问题描述 VMware Centos环境&#xff0c;根分区为LVM&#xff0c;大小50G&#xff0c;现在需要对根分区扩容。我添加了一块500G的虚拟硬盘(/dev/sdb)&#xff0c;如何把这500G扩容到根分区&#xff1f; LVM扩容方法 1. 对新磁盘分区 使用fdisk /dev/sdb命令&#xff0c;进…

SpringCloud02_consul概述、功能及下载、服务注册与发现、配置与刷新

文章目录 ①. Euraka为什么被废弃②. consul简介、如何下载③. consul功能及下载④. 服务注册与发现 - 8001改造⑤. 服务注册与发现 - 80改造⑥. 服务配置与刷新Refresh ①. Euraka为什么被废弃 ①. Eureka停更进维 ②. Eureka对初学者不友好,下图为自我保护机制 ③. 阿里巴巴…

linux下JDK的安装

前言&#xff1a; 安装部署java开发的代码都需要java环境&#xff0c;这里记录下linux下JDK的安装过程&#xff0c;仅供学习参考。 JDK的下载 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads 选择和操作系统匹配的版本进行下载 查看操作系统&…