当前位置: 首页 > news >正文

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实现步骤
  1. 初始化栈:我们需要两个栈,一个用于存储数字(表示重复次数),另一个用于存储字符串片段。

  2. 遍历输入字符串:逐个字符检查,根据不同字符类型执行相应操作。

    • 如果是数字字符,则构建完整的数字(因为数字可能不止一位)。
    • 如果是左括号 '[',则将当前数字和字符串片段压入栈,并重置当前数字和字符串片段。
    • 如果是字母字符,则将其添加到当前字符串片段中。
    • 如果是右括号 ']',则从栈中弹出之前的数字和字符串片段,根据弹出的数字重复弹出字符串片段,然后将结果字符串片段重新压入栈中(或者直接用于构建最终结果,如果栈已经为空)。
  3. 构建最终结果:遍历结束后,栈中应该只剩下一个字符串片段,即为解码后的字符串。如果栈为空(实际上在这个特定问题中不会发生,因为输入总是有效的),则结果为空字符串。

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原生数据类型(如intlong)的表示范围。虽然Java提供了BigInteger类来处理大整数运算,但在某些情况下,我们可能希望手动实现这些功能,以便更好地理解其背后的原理或满足特定的性能要求。

今天,我们将讨论如何手动实现两个以字符串形式表示的非负整数的乘法,并将结果也以字符串形式返回。这个问题看似简单,但实际上涉及到一些有趣的算法和技巧。

问题描述

给定两个以字符串形式表示的非负整数num1num2,我们需要返回它们的乘积,乘积也以字符串形式表示。这里有几个关键点需要注意:

  • num1num2的长度可能非常大(最多200位)。
  • 不能使用任何内置的BigInteger库或直接将输入转换为整数。
  • 输入的数字只包含数字字符,并且不包含任何前导零(除了数字0本身)。
解决方案:模拟手工乘法

为了解决这个问题,我们可以模拟手工乘法的过程。具体步骤如下:

  1. 初始化结果数组:创建一个足够大的整数数组来存储乘积的每一位。由于乘积的位数最多为两个乘数位数的和,因此我们可以创建一个长度为len1 + len2的数组。

  2. 双重循环计算乘积:从后往前遍历两个字符串的每一位数字,计算它们的乘积,并加上之前的结果(如果有进位)。然后,更新当前位的值和进位到下一位的值。

  3. 构建结果字符串:遍历结果数组,将每一位数字添加到字符串中,注意跳过前导零。

  4. 处理特殊情况:如果结果为空(即所有位都是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"// 可以添加更多测试用例来验证代码的正确性}
}

 

代码解释

  • 边界情况处理:如果num1num2为"0",则直接返回"0"。
  • 双重循环:使用两个嵌套的循环来遍历两个字符串的每一位数字,并计算乘积。
  • 更新结果数组:计算当前两位数字的乘积,并加上之前的结果(如果有进位),然后更新当前位的值和进位到下一位的值。
  • 构建结果字符串:遍历结果数组,将每一位数字添加到StringBuilder对象中,并跳过前导零。
  • 返回结果:如果结果为空,则返回"0";否则,返回构建好的字符串。
测试用例

main方法中,我们添加了一些测试用例来验证代码的正确性。这些测试用例包括简单的数字、较大的数字和边界情况(如0)。你可以根据需要添加更多的测试用例来确保代码的健壮性。

总结

通过手动实现大整数乘法,我们不仅能够更好地理解其背后的原理,还能在特定情况下获得更好的性能。虽然Java提供了BigInteger类来简化大整数运算,但手动实现这些功能仍然是一个有价值的练习。

希望这篇博客能够帮助你更好地理解大整数乘法的问题及其解决方案!如果你有任何问题或建议,请随时在评论区留言。

相关文章:

Java每日精进·45天挑战·Day18

一、解码嵌套编码字符串 在编程中&#xff0c;我们经常遇到需要对特定格式的字符串进行解析和解码的任务。今天&#xff0c;我们来探讨一个具体的例子&#xff1a;如何解码一个按照特定规则编码的字符串。这个规则允许字符串中的一部分被重复多次&#xff0c;且这种重复可以嵌…...

C# 中用于比较两个字符串的方法string.Compare

string.Compare 是 C# 中用于比较两个字符串的方法。它返回一个整数&#xff0c;表示两个字符串在字典顺序&#xff08;lexicographical order&#xff09;中的相对关系。这个方法非常有用&#xff0c;尤其是在排序、查找或比较字符串时。 string.Compare 的详细说明 方法签名…...

进阶数据结构——树状数组

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

键盘启用触摸板-tips

在日常使用笔记本电脑时&#xff0c;我们会遇到没带鼠标&#xff0c;触摸板关闭的情况&#xff0c;通常情况下&#xff0c;我们习惯通过鼠标点击或触摸屏操作来启用触摸板&#xff0c;但其实通过键盘也能轻松实现这一功能。以下就是一种通过键盘操作启用触摸板的方法&#xff0…...

信息安全之网络安全

网络安全技术是一类包含内容极其广泛的技术&#xff0c;广义上说任何检测、防御和抵制网络攻击的技术都属于网络安全技术&#xff0c;而且很多网络安全技术都是攻击驱动型的。 网络安全大致包含的内容主要有防火墙&#xff0c;入侵检测&#xff0c;漏洞扫描与网络隔离&#xf…...

成都国际数字影像产业园布局者树莓集团,亮相宜宾翠屏招商签约

在商业版图的不断拓展中&#xff0c;树莓集团始终以敏锐的市场洞察力和果敢的决策力占据先机。近期&#xff0c;作为成都国际数字影像产业园的布局者&#xff0c;树莓集团高调亮相宜宾翠屏招商签约盛会&#xff0c;引发行业内外的广泛关注。 宜宾翠屏招商签约盛会&#xff0c;…...

opencascade 获取edge起始点 会出现终点与实际不同的情况

在使用 OpenCASCADE 获取 TopoDS_Edge 的起始点和终点时&#xff0c;可能会出现终点与实际不一致的情况。这通常是由于以下原因导致的&#xff1a; 几何曲线的方向问题&#xff1a;在某些情况下&#xff0c;几何曲线的方向可能与拓扑边的方向不一致&#xff0c;导致通过几何曲线…...

掌握正则表达式_模式匹配的艺术

当然,以下是《掌握正则表达式:模式匹配的艺术》文章内容,使用 Java 正则表达式,并包含丰富的代码示例: 1. 引言 1.1 正则表达式的定义与历史 正则表达式(Regular Expression,简称 regex 或 regexp)是一种用于描述文本模式的强大工具。它最初由数学家 Stephen Kleene…...

【蓝桥】二维DP--摆花

&#x1f4cc;题目描述 &#x1f4cc;解题思路 &#x1f4cc;完整代码 &#x1f4cc;举例 &#x1f4cc;题目描述 &#x1f4cc;解题思路 动态规划&#xff08;DP&#xff09; 问题&#xff0c;核心是 “前 i 种物品&#xff0c;每种物品最多可以使用x 次&#xff0c;组成总和…...

在AMLOGIC android14 平台上使用adb

1.修改bootloader 编译&#xff1a;添加 --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&#xff08;又称V93K&#xff09;是Advantest公司推出的高端可扩展SoC测试平台&#xff0c;在半导体测试领域具有标杆地位。以下为该设备的详细介绍&#xff1a; ### 一、核心性能与技术优势 1. **高速高精度测试能力** V9300支持高达112 Gbps PAM4信号&…...

【机器学习】监督学习-决策树-CART(Classification and Regression Tree,分类与回归树)详尽版

CART&#xff08;Classification and Regression Trees&#xff09;法 CART&#xff08;分类与回归树&#xff09;是一种决策树算法&#xff0c;由 Breiman 等人在 1984 年提出。它用于构建分类树&#xff08;Classification Tree&#xff09;或回归树&#xff08;Regression …...

Navicat 迁移数据库 传输数据

Navicat提供的数据传输功能&#xff0c;很好用&#xff0c;可以从一个数据库迁移到另外一个数据库。 步骤&#xff1a;菜单栏----工具—传输—选择源连接和数据库----选择目的地连接和数据库...

Jetpack Compose初体验

入门学习 由于工作需要&#xff0c;我们当前要在老代码的基础上使用 Compose 进行新页面的开发&#xff0c;这项工作主要落在我的身上。因此&#xff0c;我需要先了解 Compose。 这里我入门看的是写给初学者的Jetpack Compose教程&#xff0c;Lazy Layout&#xff0c;有兴趣可…...

ceph部署-14版本(nautilus)-使用ceph-ansible部署实验记录

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、环境信息二、部署步骤2.1 基础环境准备2.2 各节点docker环境安装2.3 搭建互信集群2.4 下载ceph-ansible 三、配置部署文件3.1 使用本地docker3.2 配置hosts…...

【C++】C++ 旅馆管理系统(含 源码+报告)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 系列文章目录 目录 系列文章目录一、设计要求二、设…...

快速排序

目录 什么是快速排序&#xff1a; 图解&#xff1a; 递归法&#xff1a; 方法一&#xff08;Hoare法&#xff09;&#xff1a; 代码实现&#xff1a; 思路分析&#xff1a; 方法二&#xff08;挖坑法&#xff09;&#xff1a; 代码实现&#xff1a; 思路分析&#xff1a; 非递…...

国内 ChatGPT Plus/Pro 订阅教程

1. 登录 chat.openai.com 依次点击 Login &#xff0c;输入邮箱和密码 2. 点击升级 Upgrade 登录自己的 OpenAI 帐户后&#xff0c;点击左下角的 Upgrade to Plus&#xff0c;在弹窗中选择 Upgrade plan。 如果升级入口无法点击&#xff0c;那就访问这个网址&#xff0c;htt…...

易仓科技ai面试

请解释PHP中的面向对象编程的基本概念&#xff0c;并举例说明如何在PHP中定义一个类。 回答思路&#xff1a;需理解类、对象、继承和多态等基本概念&#xff0c;并能通过实例代码展示如何定义类及其属性和方法。 . 类&#xff08;Class&#xff09; 类是一个封装了数据和操作…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

Monorepo架构: Nx Cloud 扩展能力与缓存加速

借助 Nx Cloud 实现项目协同与加速构建 1 &#xff09; 缓存工作原理分析 在了解了本地缓存和远程缓存之后&#xff0c;我们来探究缓存是如何工作的。以计算文件的哈希串为例&#xff0c;若后续运行任务时文件哈希串未变&#xff0c;系统会直接使用对应的输出和制品文件。 2 …...