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

华为OD机试真题---字符串化繁为简

华为OD机试真题中的“字符串化繁为简”题目是一个涉及字符串处理和等效关系传递的问题。以下是对该题目的详细解析:

一、题目描述

给定一个输入字符串,字符串只可能由英文字母(a~z、A~Z)和左右小括号((、))组成。当字符里存在小括号时,小括号是成对的,可以有一个或多个小括号对,小括号对不会嵌套,小括号对内可以包含1个或多个英文字母也可以不包含英文字母。要求对这个输入字符串做简化,输出一个新的字符串,满足以下条件:

  1. 输出字符串里只需保留输入字符串里的没有被小括号对包含的字符(按照输入字符串里的字符顺序)。

  2. 将每个字符替换为在小括号对里包含的字典序最小的等效字符。等效关系定义如下:

    • 当小括号对内包含多个英文字母时,这些字母之间是相互等效的关系。
    • 等效关系可以在不同的小括号对之间传递,即当存在a和b等效和存在b和c等效时,a和c也等效。
    • 同一个英文字母的大写字母和小写字母也相互等效(即使它们分布在不同的括号对里)。

如果简化后的字符串为空,则输出为“0”。

二、示例

  1. 示例1

    • 输入:()abd
    • 输出:abd
    • 说明:输入字符串里没有被小括号包含的字符串为"abd",其中每个字符没有等效字符,输出为"abd"。
  2. 示例2

    • 输入:(abd)demand(fb)()for
    • 输出:aemanaaor
    • aabebmnor。
    • 说明:等效字符集为(a,b,d,f),输入字符串里没有被小括号包含的字符串集合为"demandfor",将其中字符替换为字典序最小的等效字符后输出为:“aemanaaor”。
  3. 示例3

    • 输入:happy(xyz)new(wxy)year(t)
    • 输出:happwnewwear
    • 说明:等效字符集为(w,x,y,z),输入字符串里没有被小括号包含的字符串集合为"happynewyear",将其中字符替换为字典序最小的等效字符后输出为:“happwnewwear”。

三、解题思路

  1. 提取等效字符

    • 遍历输入字符串,使用栈(stack)来识别和处理小括号对。
    • 当遇到左括号"("时,将其位置压入栈中。
    • 当遇到右括号")"时,弹出栈顶的左括号位置,并计算这对括号之间的字符作为等效字符集合。
    • 将这些等效字符转换为小写(或大写,以保持一致性),并放入一个集合(set)中去重。
  2. 构建等效关系

    • 使用并查集(Union Find)数据结构来维护等效关系。
    • 遍历等效字符集合,将每个字符与其等效的字符合并到同一个集合中。
  3. 替换字符

    • 遍历输入字符串中未被小括号包含的字符部分。
    • 对于每个字符,检查它是否属于某个等效字符集合。
    • 如果是,则将其替换为该集合中字典序最小的字符。
  4. 输出结果

    • 将替换后的字符按照原顺序拼接成新的字符串。
    • 如果新字符串为空,则输出"0"。

四、代码实现

import java.util.Collections;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.Set;
import java.util.Stack;public class StringSimplification {/*** 主函数入口* 该函数提示用户输入一个字符串,然后调用simplifyString方法处理该字符串* 需要处理输入流的异常,确保程序的健壮性* @param args 命令行参数,未使用*/public static void main(String[] args) {try (Scanner scanner = new Scanner(System.in)) {// 提示用户输入字符串System.out.print("请输入字符串: ");String input = scanner.nextLine();// 输入验证if (input == null || input.trim().isEmpty()) {System.out.println("输入不能为空");return;}// 调用方法处理输入的字符串,并打印结果String result = simplifyString(input);System.out.println(result);} catch (InputMismatchException ime) {// 处理输入格式错误异常System.err.println("输入格式错误: " + ime.getMessage());} catch (NoSuchElementException nse) {// 处理输入流结束异常System.err.println("输入流已结束,请确保在提示后输入字符串: " + nse.getMessage());} catch (Exception e) {// 处理其他异常System.err.println("发生错误: " + e.getMessage());e.printStackTrace(); // 打印堆栈跟踪}}/*** 简化给定的字符串,通过等效字符替换和括号规则* * @param input 待简化的输入字符串,包含字母和括号* @return 简化后的字符串,其中等效字符被替换为字典序最小的字符,且不包含括号* @throws IllegalArgumentException 如果括号不匹配,则抛出此异常*/public static String simplifyString(String input) {// 使用并查集来维护等效关系UnionFind uf = new UnionFind(26 * 2); // 26个小写字母和26个大写字母// 用于存储等效字符集合Set<Character> currentSet = new HashSet<>();// 用于处理括号匹配Stack<Integer> parenthesisStack = new Stack<>();// 用于构建未被括号包含的字符序列StringBuilder newStr = new StringBuilder();// 遍历输入字符串for (int i = 0; i < input.length(); i++) {char c = input.charAt(i);if (c == '(') {// 遇到左括号,压入栈中parenthesisStack.push(i);currentSet.clear();System.out.println("遇到左括号,当前索引: " + i);} else if (c == ')') {// 遇到右括号,处理等效字符集合if (parenthesisStack.isEmpty()) {throw new IllegalArgumentException("括号不匹配");}int startIndex = parenthesisStack.pop();// 检查括号内是否有字符if (startIndex + 1 < i) {StringBuilder sb = new StringBuilder(input.substring(startIndex + 1, i));// 将等效字符转换为小写并去重for (char ch : sb.toString().toCharArray()) {ch = Character.toLowerCase(ch);currentSet.add(ch);}// 维护等效关系if (!currentSet.isEmpty()) {char minChar = Collections.min(currentSet);for (char ch : currentSet) {if (Character.isLowerCase(ch)) {uf.union(ch - 'a', minChar - 'a');} else if (Character.isUpperCase(ch)) {uf.union(ch - 'A' + 26, minChar - 'a' + 26);}}currentSet.clear();}}} else {// 非括号字符,添加到 newStr 中newStr.append(c);System.out.println("添加非括号字符: " + c);}}// 检查是否有未匹配的左括号if (!parenthesisStack.isEmpty()) {throw new IllegalArgumentException("括号不匹配");}// 替换 newStr 中的字符为等效字符集合中的最小字符StringBuilder simplifiedStr = new StringBuilder();for (char c : newStr.toString().toCharArray()) {char lowerC = Character.toLowerCase(c);int root = uf.find(lowerC - 'a'); // 查找等效字符集合的根节点(最小字符)char minEquivChar = (char)('a' + root);simplifiedStr.append(minEquivChar);System.out.println("替换字符: " + c + " -> " + minEquivChar);}// 如果简化后的字符串为空,则返回 "0"return simplifiedStr.length() == 0 ? "0" : simplifiedStr.toString();}// 并查集数据结构static class UnionFind {private int[] parent;public UnionFind(int n) {parent = new int[n];for (int i = 0; i < n; i++) {parent[i] = i;}}public int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]); // 路径压缩,将x的父节点直接指向根节点}return parent[x];}public void union(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX != rootY) {parent[rootX] = rootY; // 将x的根节点指向y的根节点}}}
}

五、注意事项

  1. 处理大小写:在构建等效关系和替换字符时,需要注意大小写字母之间的等效关系。可以将所有字符转换为小写(或大写)来处理。
  2. 边界条件:注意处理输入字符串为空或只包含括号等特殊情况。
  3. 性能优化:使用并查集数据结构来高效地维护等效关系,避免使用复杂的嵌套循环或递归结构。

通过上述解析和代码实现,可以有效地解决华为OD机试中的“字符串化繁为简”问题。

http://www.lryc.cn/news/487755.html

相关文章:

  • 概念解读|K8s/容器云/裸金属/云原生...这些都有什么区别?
  • 初识Arkts
  • 基本的SELECT语句
  • 51c自动驾驶~合集30
  • Python Tutor网站调试利器
  • h5小游戏实现获取本机图片
  • 前端 javascript a++和++a的区别
  • OceanBase V4.x应用实践:如何排查表被锁问题
  • ctfshow-web入门-SSRF(web351-web360)
  • 【日常记录-Git】如何为post-checkout脚本传递参数
  • 《机器人控制器设计与编程》考试试卷**********大学2024~2025学年第(1)学期
  • 后台管理系统(开箱即用)
  • 5G CPE与4G CPE的主要区别有哪些
  • 量化交易系统开发-实时行情自动化交易-4.1.3.A股平均趋向指数(ADX)实现
  • tcp的网络惊群问题
  • 云原生之运维监控实践-使用Prometheus与Grafana实现对Nginx和Nacos服务的监测
  • 软考教材重点内容 信息安全工程师 第 4 章 网络安全体系与网络安全模型
  • 机器学习——期末复习 重点题归纳
  • MYSQL——数据更新
  • Vite 基础理解及应用
  • [JAVA]用MyBatis框架实现一个简单的数据查询操作
  • CSS 样式的优先级?
  • Linux驱动开发快速入门——字符设备驱动(直接操作寄存器设备树版)
  • 数据结构《栈和队列》
  • C# 超链接控件LinkLabel无法触发Alt快捷键
  • JVM类加载过程-Loading
  • 2024年11月19日Github流行趋势
  • 详细描述一下Elasticsearch索引文档的过程?
  • 基于css的Grid布局和vue实现点击左移右移轮播过渡动画效果
  • HarmonyOS NEXT应用元服务开发Intents Kit(意图框架服务)习惯推荐方案概述