LeetCode 394, 61, 100

news2024/11/13 10:08:21

目录

  • 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 都是 null
            return true; // 则返回 true
        } else if (p == null || q == null) { // 此时 p, q 只有一个是 null
            return 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 都是 null
            return true; // 则返回 true
        } else if (p == null || q == null) { // 此时 p, q 只有一个是 null
            return false; // 则返回 false
        }

        LinkedList<TreeNode> queueP = new LinkedList<>(); // 用于遍历二叉树 p
        LinkedList<TreeNode> queueQ = new LinkedList<>(); // 用于遍历二叉树 q
        queueP.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)) { // 如果对应的节点只有一个为null
                return false; // 则返回 false
            }
            // 可以使用 rightP == null ^ rightQ == null 作为判断条件,它与以下条件等价
            if ((rightP == null && rightQ != null)
                    || (rightP != null && rightQ == null)) { // 如果对应的节点只有一个为null
                return 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.coloradmin.cn/o/1935045.html

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

相关文章

嵌入式物联网在医疗行业中的应用——案例分析

作者主页: 知孤云出岫 目录 嵌入式物联网在医疗行业中的应用——案例分析引言1. 智能病房监控1.1 实时患者监控系统 2. 智能医疗设备管理2.1 设备使用跟踪与维护 3. 智能药物管理3.1 药物分配与跟踪 4. 智能远程医疗4.1 远程患者监控与诊断 总结 嵌入式物联网在医疗行业中的应…

3、宠物商店智能合约实战(truffle智能合约项目实战)

3、宠物商店智能合约实战&#xff08;truffle智能合约项目实战&#xff09; 1-宠物商店环境搭建、运行2-webjs与宠物逻辑实现3-领养智能合约初始化4-宠物领养实现5-更新宠物领养状态 1-宠物商店环境搭建、运行 https://www.trufflesuite.com/boxes/pet-shop 这个还是不行 或者…

Blender4.2版本正式上线,新版本的5个主要功能!

​Blender刚刚推出了备受瞩目的 Blender 4.2 版本&#xff0c;这款软件专为那些在视觉特效、动画制作、游戏开发和可视化设计领域工作的艺术家们量身打造。作为最新的长期稳定更新&#xff0c;Blender 4.2 不仅稳定可靠&#xff0c;还引入了备受期待的“Eevee Next”实时渲染引…

【BUG】已解决:zipfile.BadZipFile: File is not a zip file

已解决&#xff1a;zipfile.BadZipFile: File is not a zip file 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发…

channle介绍

通道在Java NIO&#xff08;New Input/Output&#xff09;中扮演着核心角色&#xff0c;它们是与Buffer&#xff08;缓冲区&#xff09;交互的入口点&#xff0c;用于从外部资源读取数据到内存或从内存写入数据到外部资源。通道可以看作是访问文件数据和其他I/O资源&#xff08…

JVM:MAT内存泄漏检测原理

文章目录 一、介绍 一、介绍 MAT提供了称为支配树&#xff08;Dominator Tree&#xff09;的对象图。支配树展示的是对象实例间的支配关系。在对象引用图中&#xff0c;所有指向对象B的路径都经过对象A&#xff0c;则认为对象A支配对象B。 支配树中对象本身占用的空间称之为…

谷歌浏览器自动填充密码时,el-input样式错乱

使用到谷歌浏览器的记忆功能&#xff0c;选择的内容为浏览器保存的内容时 会导致element-plus的el-input样式改变 只需要增加一个css样式&#xff0c;就可以解决问题 :deep .el-input__inner {box-shadow: 0 0 0 1000px #fff inset; }修改后

深入理解ADB:Android调试桥详解与使用指南

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Android ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 1. 什么是ADB&#xff1f; ADB的基本原理&#xff1a; 2. ADB的安装与配置 安装ADB工具集&#xff1a; 配置ADB环境变量&am…

注册安全分析报告:东方航空

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

进程与线程(一)进程相关

目录 一. 概念二 . 组成进程控制块程序段数据段 三. 特征四. 进程的状态与转换五. 进程控制进程创建进程终止进程阻塞与进程唤醒进程切换 六. 进程通信共享存储消息传递管道通信 一. 概念 多道程序环境下&#xff0c;允许多个程序并发执行&#xff0c;此时它们将失去封闭性&…

Unity 导入MRTK,使用URP 升级材质,MRTK的材质还是洋红色

控制台显示信息 ToggleBackground material was not upgraded. There’s no upgrader to convert Mixed Reality Toolkit/Standard shader to selected pipeline UnityEditor.Rendering.Universal.UniversalRenderPipelineMaterialUpgrader:UpgradeProjectMaterials() (at 点击…

出现 Welcome to nginx! If you see this page, 的解决方法

目录 前言1. 问题所示2. 原理分析3. 解决方法 前言 对于Nginx的知识点推荐阅读&#xff1a; Nginx从入门到精通&#xff08;全&#xff09;Nginx配置静态网页访问&#xff08;图文界面&#xff09;Nginx将https重定向为http进行访问的配置&#xff08;附Demo&#xff09; 由…

经典神经网络(14)T5模型原理详解及其微调(文本摘要)

经典神经网络(14)T5模型原理详解及其微调(文本摘要) 2018 年&#xff0c;谷歌发布基于双向 Transformer 的大规模预训练语言模型 BERT&#xff0c;而后一系列基于 BERT 的研究工作如春笋般涌现&#xff0c;预训练模型也成为了业内解决 NLP 问题的标配。 2019年&#xff0c;谷歌…

【BUG】已解决:ModuleNotFoundError: No module named ‘torch‘

已解决&#xff1a;ModuleNotFoundError: No module named ‘torch‘ 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市…

UE4-蓝图(可视化编程)学习

一.开关门交互实现 1.需要用到的模板和内容包 2.给门添加碰撞 进入第三人称模板场景&#xff0c;找到门的模型&#xff0c;并将门的模型添加到我们的场景中&#xff1a; 此时我们运行游戏&#xff0c;会发现我们的角色可以穿过我们门的模型&#xff0c;说明我们没有给门添加碰…

MAVSDK-Java开源库的SDK库macOS平台编译

1.先安装好JDK17 2.克隆MAVSDK-Java源码 3.检测工程./gradlew check 发现未安装protoc-gen-mavsdk 安装后要添加到环境变量 4.安装protoc-gen-mavsdk pip3 install protoc-gen-mavsdk安装路径为: /opt/anaconda3/lib/python3.11/site-packages/protoc_gen_mavsdk

处理.git文件夹过大出现臃肿问题

1、问题背景 在软件开发过程中&#xff0c;版本控制是一个至关重要的环节。Git 作为一种流行的分布式版本控制系统&#xff0c;被广泛应用于各种项目中。然而&#xff0c;近期我们发现在进行项目发版时&#xff0c;Git 克隆项目的时间显著增加&#xff0c;严重影响了发版的效率…

Golang | Leetcode Golang题解之第257题二叉树的所有路径

题目&#xff1a; 题解&#xff1a; func binaryTreePaths(root *TreeNode) []string {paths : []string{}if root nil {return paths}nodeQueue : []*TreeNode{}pathQueue : []string{}nodeQueue append(nodeQueue, root)pathQueue append(pathQueue, strconv.Itoa(root.V…

GaussDB常见调优指南

文章目录 GaussDB常见调优指南一. Analyze 统计信息解析二. Explain 分布式计划解析三. 性能调优总体策略详解四. 性能调优之坏味道 SQL 识别五. 性能调优之好味道表定义六. 性能调优之 SQL 改写七. 性能调优之路径干预八. 性能调优之 Plan hint 运用九. 性能调优之 GUC 参数调…

【Anaconda】Ubuntu配置与windows远程访问

下载安装 # 下载(进官网复制最新下载地址) wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh# 安装 bash Anaconda3-2024.06-1-Linux-x86_64.sh配置环境 # 编辑环境变量 nano ~/.bashrc# 加入以下这行内容&#xff0c;user替换为自己的用户名 ex…