Java每日精进·45天挑战·Day18
一、解码嵌套编码字符串
在编程中,我们经常遇到需要对特定格式的字符串进行解析和解码的任务。今天,我们来探讨一个具体的例子:如何解码一个按照特定规则编码的字符串。这个规则允许字符串中的一部分被重复多次,且这种重复可以嵌套。
问题描述
给定一个经过编码的字符串,我们需要返回它解码后的字符串。编码规则如下:
k[encoded_string]
:表示其中方括号内部的encoded_string
正好重复k
次。k
保证为正整数,且不会出现像3a
或2[4]
这样的无效输入。- 输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
示例
-
输入:
s = "3[a]2[bc]"
-
输出:
"aaabcbc"
-
输入:
s = "3[a2[c]]"
-
输出:
"accaccacc"
-
输入:
s = "2[abc]3[cd]ef"
-
输出:
"abcabccdcdcdef"
解决方案:使用栈
为了解决这个问题,我们可以利用栈这种数据结构。栈非常适合处理嵌套结构,因为它遵循后进先出的原则,这与我们解析嵌套编码字符串时需要的操作顺序相吻合。
Java实现步骤
-
初始化栈:我们需要两个栈,一个用于存储数字(表示重复次数),另一个用于存储字符串片段。
-
遍历输入字符串:逐个字符检查,根据不同字符类型执行相应操作。
- 如果是数字字符,则构建完整的数字(因为数字可能不止一位)。
- 如果是左括号 '[',则将当前数字和字符串片段压入栈,并重置当前数字和字符串片段。
- 如果是字母字符,则将其添加到当前字符串片段中。
- 如果是右括号 ']',则从栈中弹出之前的数字和字符串片段,根据弹出的数字重复弹出字符串片段,然后将结果字符串片段重新压入栈中(或者直接用于构建最终结果,如果栈已经为空)。
-
构建最终结果:遍历结束后,栈中应该只剩下一个字符串片段,即为解码后的字符串。如果栈为空(实际上在这个特定问题中不会发生,因为输入总是有效的),则结果为空字符串。
Java代码实现
以下是完整的Java代码实现:
import java.util.Stack;public class Solution {public String decodeString(String s) {Stack<Integer> counts = new Stack<>();Stack<StringBuilder> strings = new Stack<>();StringBuilder currentString = new StringBuilder();int currentCount = 0;for (char c : s.toCharArray()) {if (Character.isDigit(c)) {currentCount = currentCount * 10 + (c - '0');} else if (c == '[') {counts.push(currentCount);strings.push(currentString);currentCount = 0;currentString = new StringBuilder();} else if (Character.isLetter(c)) {currentString.append(c);} else if (c == ']') {StringBuilder temp = currentString;int repeatTimes = counts.pop();currentString = strings.pop();for (int i = 0; i < repeatTimes; i++) {currentString.append(temp);}}}return currentString.toString();}public static void main(String[] args) {Solution solution = new Solution();System.out.println(solution.decodeString("3[a]2[bc]")); // 输出: aaabcbcSystem.out.println(solution.decodeString("3[a2[c]]")); // 输出: accaccaccSystem.out.println(solution.decodeString("2[abc]3[cd]ef")); // 输出: abcabccdcdcdefSystem.out.println(solution.decodeString("abc3[cd]xyz")); // 输出: abccdcdcdxyz}
}
代码解释与测试
- 变量初始化:我们初始化了两个栈
counts
和strings
分别用于存储数字和字符串片段,以及两个变量currentString
和currentCount
用于构建当前的字符串片段和数字。 - 遍历字符串:我们逐个字符检查输入字符串,并根据字符类型执行相应的操作。特别地,当遇到右括号 ']' 时,我们从栈中弹出之前的数字和字符串片段,并根据弹出的数字重复弹出字符串片段。
- 返回结果:遍历结束后,
currentString
中存储的就是解码后的字符串。
为了验证代码的正确性,我们在 main
方法中添加了一些测试用例,并打印了输出结果。这些测试用例涵盖了不同的嵌套情况和重复次数,确保了代码的健壮性和正确性。
总结
通过使用栈这种数据结构,我们能够高效地解析和解码嵌套编码字符串。这种方法不仅简单易懂,而且具有很好的扩展性和鲁棒性。希望这篇博客能够帮助你更好地理解这个问题及其解决方案!
二、大整数乘法:手动实现字符串形式的数字相乘
在编程中,我们有时会遇到需要处理非常大的数字的情况,这些数字超出了Java原生数据类型(如int
、long
)的表示范围。虽然Java提供了BigInteger
类来处理大整数运算,但在某些情况下,我们可能希望手动实现这些功能,以便更好地理解其背后的原理或满足特定的性能要求。
今天,我们将讨论如何手动实现两个以字符串形式表示的非负整数的乘法,并将结果也以字符串形式返回。这个问题看似简单,但实际上涉及到一些有趣的算法和技巧。
问题描述
给定两个以字符串形式表示的非负整数num1
和num2
,我们需要返回它们的乘积,乘积也以字符串形式表示。这里有几个关键点需要注意:
num1
和num2
的长度可能非常大(最多200位)。- 不能使用任何内置的
BigInteger
库或直接将输入转换为整数。 - 输入的数字只包含数字字符,并且不包含任何前导零(除了数字0本身)。
解决方案:模拟手工乘法
为了解决这个问题,我们可以模拟手工乘法的过程。具体步骤如下:
-
初始化结果数组:创建一个足够大的整数数组来存储乘积的每一位。由于乘积的位数最多为两个乘数位数的和,因此我们可以创建一个长度为
len1 + len2
的数组。 -
双重循环计算乘积:从后往前遍历两个字符串的每一位数字,计算它们的乘积,并加上之前的结果(如果有进位)。然后,更新当前位的值和进位到下一位的值。
-
构建结果字符串:遍历结果数组,将每一位数字添加到字符串中,注意跳过前导零。
-
处理特殊情况:如果结果为空(即所有位都是0),则返回字符串"0"。
Java代码实现
以下是Java代码的实现:
public class Solution {public String multiply(String num1, String num2) {if (num1.equals("0") || num2.equals("0")) {return "0";}int len1 = num1.length();int len2 = num2.length();int[] result = new int[len1 + len2]; // 用于存储乘积的每一位,可能最长为len1+len2位// 从后往前遍历num1和num2的每一位数字for (int i = len1 - 1; i >= 0; i--) {for (int j = len2 - 1; j >= 0; j--) {int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0'); // 计算当前两位数字的乘积int sum = mul + result[i + j + 1]; // 加上之前的结果(如果有进位)// 更新当前位的值result[i + j + 1] = sum % 10;// 更新进位到下一位result[i + j] += sum / 10;}}// 构建结果字符串StringBuilder sb = new StringBuilder();for (int num : result) {if (!(sb.length() == 0 && num == 0)) { // 跳过前导零sb.append(num);}}return sb.length() == 0 ? "0" : sb.toString(); // 如果结果为空,则返回"0"}public static void main(String[] args) {Solution solution = new Solution();System.out.println(solution.multiply("2", "3")); // 输出: "6"System.out.println(solution.multiply("123", "456")); // 输出: "56088"// 可以添加更多测试用例来验证代码的正确性}
}
代码解释
- 边界情况处理:如果
num1
或num2
为"0",则直接返回"0"。 - 双重循环:使用两个嵌套的循环来遍历两个字符串的每一位数字,并计算乘积。
- 更新结果数组:计算当前两位数字的乘积,并加上之前的结果(如果有进位),然后更新当前位的值和进位到下一位的值。
- 构建结果字符串:遍历结果数组,将每一位数字添加到
StringBuilder
对象中,并跳过前导零。 - 返回结果:如果结果为空,则返回"0";否则,返回构建好的字符串。
测试用例
在main
方法中,我们添加了一些测试用例来验证代码的正确性。这些测试用例包括简单的数字、较大的数字和边界情况(如0)。你可以根据需要添加更多的测试用例来确保代码的健壮性。
总结
通过手动实现大整数乘法,我们不仅能够更好地理解其背后的原理,还能在特定情况下获得更好的性能。虽然Java提供了BigInteger
类来简化大整数运算,但手动实现这些功能仍然是一个有价值的练习。
希望这篇博客能够帮助你更好地理解大整数乘法的问题及其解决方案!如果你有任何问题或建议,请随时在评论区留言。
相关文章:
Java每日精进·45天挑战·Day18
一、解码嵌套编码字符串 在编程中,我们经常遇到需要对特定格式的字符串进行解析和解码的任务。今天,我们来探讨一个具体的例子:如何解码一个按照特定规则编码的字符串。这个规则允许字符串中的一部分被重复多次,且这种重复可以嵌…...
C# 中用于比较两个字符串的方法string.Compare
string.Compare 是 C# 中用于比较两个字符串的方法。它返回一个整数,表示两个字符串在字典顺序(lexicographical order)中的相对关系。这个方法非常有用,尤其是在排序、查找或比较字符串时。 string.Compare 的详细说明 方法签名…...

进阶数据结构——树状数组
前言 看这篇文章前我建议你们先看这个视频还有这个视频,不然你们可能看不懂。 一、树状数组的核心思想与本质 核心思想:树状数组(Fenwick Tree)是一种用于高效处理前缀和查询和单点更新的数据结构。 本质:通过二进…...

键盘启用触摸板-tips
在日常使用笔记本电脑时,我们会遇到没带鼠标,触摸板关闭的情况,通常情况下,我们习惯通过鼠标点击或触摸屏操作来启用触摸板,但其实通过键盘也能轻松实现这一功能。以下就是一种通过键盘操作启用触摸板的方法࿰…...
信息安全之网络安全
网络安全技术是一类包含内容极其广泛的技术,广义上说任何检测、防御和抵制网络攻击的技术都属于网络安全技术,而且很多网络安全技术都是攻击驱动型的。 网络安全大致包含的内容主要有防火墙,入侵检测,漏洞扫描与网络隔离…...
成都国际数字影像产业园布局者树莓集团,亮相宜宾翠屏招商签约
在商业版图的不断拓展中,树莓集团始终以敏锐的市场洞察力和果敢的决策力占据先机。近期,作为成都国际数字影像产业园的布局者,树莓集团高调亮相宜宾翠屏招商签约盛会,引发行业内外的广泛关注。 宜宾翠屏招商签约盛会,…...
opencascade 获取edge起始点 会出现终点与实际不同的情况
在使用 OpenCASCADE 获取 TopoDS_Edge 的起始点和终点时,可能会出现终点与实际不一致的情况。这通常是由于以下原因导致的: 几何曲线的方向问题:在某些情况下,几何曲线的方向可能与拓扑边的方向不一致,导致通过几何曲线…...
掌握正则表达式_模式匹配的艺术
当然,以下是《掌握正则表达式:模式匹配的艺术》文章内容,使用 Java 正则表达式,并包含丰富的代码示例: 1. 引言 1.1 正则表达式的定义与历史 正则表达式(Regular Expression,简称 regex 或 regexp)是一种用于描述文本模式的强大工具。它最初由数学家 Stephen Kleene…...

【蓝桥】二维DP--摆花
📌题目描述 📌解题思路 📌完整代码 📌举例 📌题目描述 📌解题思路 动态规划(DP) 问题,核心是 “前 i 种物品,每种物品最多可以使用x 次,组成总和…...
在AMLOGIC android14 平台上使用adb
1.修改bootloader 编译:添加 --fastboot-write cd bootloader/uboot-repo ./mk s7d_bm201 --vab --avb2 --fastboot-write #./mk s7_bh201 --avb2 --vab --fastboot-write echo "compiled bootloader success!!!" cp build/u-boot.bin.signed ../../dev…...
力扣-二叉树-222 完全二叉树节点的数量
思路1 利用层序遍历所有节点即可 代码1 class Solution { public:int countNodes(TreeNode* root) {if(root nullptr) return 0;queue<TreeNode*> que;que.push(root);int size 0;while(!que.empty()){size que.size();int length que.size();while(length--){Tre…...
V93K测试机
爱德万V9300(又称V93K)是Advantest公司推出的高端可扩展SoC测试平台,在半导体测试领域具有标杆地位。以下为该设备的详细介绍: ### 一、核心性能与技术优势 1. **高速高精度测试能力** V9300支持高达112 Gbps PAM4信号&…...

【机器学习】监督学习-决策树-CART(Classification and Regression Tree,分类与回归树)详尽版
CART(Classification and Regression Trees)法 CART(分类与回归树)是一种决策树算法,由 Breiman 等人在 1984 年提出。它用于构建分类树(Classification Tree)或回归树(Regression …...

Navicat 迁移数据库 传输数据
Navicat提供的数据传输功能,很好用,可以从一个数据库迁移到另外一个数据库。 步骤:菜单栏----工具—传输—选择源连接和数据库----选择目的地连接和数据库...
Jetpack Compose初体验
入门学习 由于工作需要,我们当前要在老代码的基础上使用 Compose 进行新页面的开发,这项工作主要落在我的身上。因此,我需要先了解 Compose。 这里我入门看的是写给初学者的Jetpack Compose教程,Lazy Layout,有兴趣可…...
ceph部署-14版本(nautilus)-使用ceph-ansible部署实验记录
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、环境信息二、部署步骤2.1 基础环境准备2.2 各节点docker环境安装2.3 搭建互信集群2.4 下载ceph-ansible 三、配置部署文件3.1 使用本地docker3.2 配置hosts…...

【C++】C++ 旅馆管理系统(含 源码+报告)【独一无二】
👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 系列文章目录 目录 系列文章目录一、设计要求二、设…...

快速排序
目录 什么是快速排序: 图解: 递归法: 方法一(Hoare法): 代码实现: 思路分析: 方法二(挖坑法): 代码实现: 思路分析: 非递…...

国内 ChatGPT Plus/Pro 订阅教程
1. 登录 chat.openai.com 依次点击 Login ,输入邮箱和密码 2. 点击升级 Upgrade 登录自己的 OpenAI 帐户后,点击左下角的 Upgrade to Plus,在弹窗中选择 Upgrade plan。 如果升级入口无法点击,那就访问这个网址,htt…...
易仓科技ai面试
请解释PHP中的面向对象编程的基本概念,并举例说明如何在PHP中定义一个类。 回答思路:需理解类、对象、继承和多态等基本概念,并能通过实例代码展示如何定义类及其属性和方法。 . 类(Class) 类是一个封装了数据和操作…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...