news 2026/1/12 16:45:36

(新卷,100分)- 字符串分割(Java JS Python)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(新卷,100分)- 字符串分割(Java JS Python)

(新卷,100分)- 字符串分割(Java & JS & Python)

题目描述

给定非空字符串s,将该字符串分割成一些子串,使每个子串的ASCII码值的和均为水仙花数。

1、若分割不成功,则返回0;

2、若分割成功且分割结果不唯一,则返回-1;

3、若分割成功且分割结果唯一,则返回分割后子串的数目。

输入描述

输入字符串的最大长度为200

输出描述

根据题目描述中情况,返回相应的结果。

备注

"水仙花数"是指一个三位数,每位上数字的立方和等于该数字本身,如 371 是’水仙花数’,因为 371=3^3+7^3+1^3

用例
输入abc
输出0
说明分割不成功
输入f3@d5a8
输出-1
说明分割成功但分割结果不唯一,可以分割为两组,一组’f3’和’@d5a8’,另外一组’f3@d5’和’a8’
输入AXdddF
输出2
说明分割成功且分割结果唯一,可以分割’AX’(153)和’dddF’(370)成两个子串
题目解析

我的解题思路如下:

首先将输入字符串变为一个ascii码值数组arr,比如f3@d5a8,就变为了 [102,51,64,100,53,97,56]

然后处理逻辑如下

let sum = 0 for(let i=0; i<arr.length; i++) { sum += arr[i] if(isSxh(sum)) { // 如果sum是水仙花数,则0~i子串可以组成水仙花数,下一个子串从i+1开始 let sum2 = 0 for(let j=i+1; j<arr.length; j++) { sum2 += arr[j] if(isSxh(sum2)) {// 如果sum2是水仙花数,则i+1~j子串可以组成水仙花数,下一个子串从j+1开始 let sum3 = 0 for(let k=j+1; k<arr.length; k++) { sum3 += arr[k] if(isSxh(sum3)) {// 如果sum3是水仙花数,则j+1~k子串可以组成水仙花数,下一个子串从k+1开始 // 重复以上逻辑 } } } } } }

可以发现,上面逻辑可以使用递归来实现,当递归到子串长度为0时结束,或者无法没有下一次递归时结束。

在递归过程中,我们可以统计到一共有多少种分割方式,每种分割方式将字符串分为几段。

如果有0种分割方式,则打印0

如果有1种分割方式,则打印该分割方式可以将字符串分为几段

如果有2种或以上分割方式,则打印-1

本题还有一个优化点,就是基于前缀和,实现O(1)时间求解任意区间的元素之和。


OJ用例库为了产生这样的子串:

ASCII码值的和均为水仙花数

因此,输入的字符串中会存在一些不常用的字符,这些字符可能会对输入获取逻辑产生影响,比如Java语言按照Scanner获取的话,则会以空白字符作为输入获取截止符,因此我们需要通过useDelimiter指定只有换行符才能截止输入获取。具体请看下面Java代码的输入获取逻辑。

对于JS和Python没有此类问题。

Java算法源码
import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in).useDelimiter("[\n]"); System.out.println(getResult(sc.next())); } public static int getResult(String s) { // 将字符串转化为ASCII数组 char[] cArr = s.toCharArray(); int n = cArr.length; // 前缀和,实现O(1)时间求解某区间内元素之和 int[] preSum = new int[n + 1]; for (int i = 1; i <= n; i++) preSum[i] = preSum[i - 1] + cArr[i - 1]; // res记录成功分割的情况 ArrayList<Integer> res = new ArrayList<>(); // 递归 recursive(preSum, n, 0, 0, res); if (res.size() == 0) return 0; else if (res.size() == 1) return res.get(0); else return -1; } public static void recursive(int[] preSum, int n, int start, int count, ArrayList<Integer> res) { if (start == n) { res.add(count); return; } for (int end = start + 1; end <= n; end++) { // 基于前缀和快速求解任意区间内的元素和 if (isSxh(preSum[end] - preSum[start])) { recursive(preSum, n, end, count + 1, res); } } } // 判断num是否为水仙花数 public static boolean isSxh(int num) { if (num <= 99 || num >= 1000) return false; int x = num / 100 % 10; int y = num / 10 % 10; int z = num % 10; return num == x * x * x + y * y * y + z * z * z; } }
JS算法源码
/* JavaScript Node ACM模式 控制台输入获取 */ const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.on("line", (line) => { console.log(getResult(line)); }); function getResult(str) { // 将字符串转化为ASCII数组 const cArr = [...str].map((ele) => ele.charCodeAt()); const n = cArr.length; // 前缀和,实现O(1)时间求解某区间内元素之和 const preSum = new Array(n + 1).fill(0); for (let i = 1; i <= n; i++) preSum[i] = preSum[i - 1] + cArr[i - 1]; // res记录成功分割的情况 const res = []; // 递归 recursive(preSum, n, 0, 0, res); if (res.length === 0) return 0; else if (res.length === 1) return res[0]; else return -1; } function recursive(preSum, n, start, count, res) { if (start === n) { res.push(count); return; } for (let end = start + 1; end <= n; end++) { // 基于前缀和快速求解任意区间内的元素和 if (isSxh(preSum[end] - preSum[start])) { recursive(preSum, n, end, count + 1, res); } } } /* 判断入参是否为水仙花数 */ function isSxh(num) { if (num <= 99 || num >= 1000) return false; const x = parseInt(num / 100) % 10; const y = parseInt(num / 10) % 10; const z = num % 10; return num == x * x * x + y * y * y + z * z * z; }
Python算法源码
# 输入获取 s = input() # 判断num是否未水仙花数 def isSxh(num): if num <= 99 or num >= 1000: return False x, y, z = [int(c) for c in str(num)] return num == x ** 3 + y ** 3 + z ** 3 # 递归分割 def recursive(preSum, n, start, count, res): if start == n: res.append(count) return for end in range(start + 1, n + 1): if isSxh(preSum[end] - preSum[start]): recursive(preSum, n, end, count + 1, res) # 算法入口 def getResult(): # 将字符串转化为ASCII数组 cArr = [ord(c) for c in s] n = len(cArr) # 前缀和,实现O(1)时间求解某区间内元素之和 preSum = [0] * (n + 1) for i in range(1, n + 1): preSum[i] = preSum[i - 1] + cArr[i - 1] # res记录成功分割的情况 res = [] # 递归分割 recursive(preSum, n, 0, 0, res) if len(res) == 0: return 0 elif len(res) == 1: return res[0] else: return -1 # 算法调用 print(getResult())
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/11 20:57:08

深度系统启动盘制作:3分钟快速上手指南

还在为安装深度操作系统发愁&#xff1f;Deepin Boot Maker让你轻松搞定启动盘制作&#xff01;这款由Linux Deepin团队开发的免费开源工具&#xff0c;专为快速创建可引导USB启动盘而生。无论你是新手还是老鸟&#xff0c;都能在几分钟内完成深度系统启动盘的制作。 【免费下载…

作者头像 李华
网站建设 2026/1/11 6:40:34

FF14副本动画智能跳过解决方案:告别重复等待

FF14副本动画智能跳过解决方案&#xff1a;告别重复等待 【免费下载链接】FFXIV_ACT_CutsceneSkip 项目地址: https://gitcode.com/gh_mirrors/ff/FFXIV_ACT_CutsceneSkip 为什么你需要这个效率优化工具 在《最终幻想XIV》的日常游戏过程中&#xff0c;重复观看相同的…

作者头像 李华
网站建设 2026/1/11 20:26:33

深度启动盘制作工具完全指南:从入门到精通

深度启动盘制作工具完全指南&#xff1a;从入门到精通 【免费下载链接】deepin-boot-maker 项目地址: https://gitcode.com/gh_mirrors/de/deepin-boot-maker 深度启动盘制作工具&#xff08;Deepin Boot Maker&#xff09;是Linux Deepin团队精心打造的一款专业级启动…

作者头像 李华
网站建设 2026/1/11 23:21:18

5分钟搞定Figma中文界面:设计师的本地化解决方案

5分钟搞定Figma中文界面&#xff1a;设计师的本地化解决方案 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma的英文界面而头疼吗&#xff1f;想要快速上手这款专业设计工具却…

作者头像 李华
网站建设 2026/1/12 17:06:56

打造专业歌词同步效果:零门槛智能制作工具指南

打造专业歌词同步效果&#xff1a;零门槛智能制作工具指南 【免费下载链接】lrc-maker 歌词滚动姬&#xff5c;可能是你所能见到的最好用的歌词制作工具 项目地址: https://gitcode.com/gh_mirrors/lr/lrc-maker 想要为心爱的歌曲制作精准同步的歌词吗&#xff1f;歌词滚…

作者头像 李华
网站建设 2026/1/13 10:24:43

Motrix终极提速指南:7个简单步骤让下载速度翻倍

Motrix终极提速指南&#xff1a;7个简单步骤让下载速度翻倍 【免费下载链接】Motrix A full-featured download manager. 项目地址: https://gitcode.com/gh_mirrors/mo/Motrix 你是不是经常遇到Motrix下载管理器明明功能强大&#xff0c;但下载速度却总是不尽如人意&am…

作者头像 李华