【华为OD机考真题】- 人民币转换(2025B卷-100分)(Java版)

🔔本文收录于「最新最全华为OD机试真题(Java版)」专栏,手把手带你零基础教学华为OD机试。本题集提供最优题解思路,解题步骤,代码解析,复杂度分析及最优题解源码等,支持多语言题解,助你轻松拿捏OD机考,一举上岸!安利大家关注&&收藏&&订阅题库正在疯狂收录中,up!up!up!!
🚫提醒:拒绝一切代考/替考,违法必究!专栏所写题库均搜集于互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验所撰,欢迎订阅。
  
💗订阅福利:一次订阅,可永久免费阅读,提供在线答疑解惑,后续题库更新皆可阅读使用!

🔥所有题目均有六种语言实现,汇总如下🔥

📚1. 题目描述

知识点:字符串处理、递归/分治算法、逻辑分支。
时间限制:1秒。
空间限制:256MB。
限定语言:不限。

📢 具体题目描述如下:

将阿拉伯数字金额转换为中文大写金额格式,需遵循以下规则:

  • 1、 前缀要求:中文大写金额前必须标明“人民币”字样。
  • 2、 用字规范:使用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样。
  • 3、 “整”字规则:
    • 金额到“元”为止时,在“元”后写“整”字(如532.00 → “人民币伍佰叁拾贰元整”)。
    • 金额含“角”或“分”时,不写“整”字(如6007.14 → “人民币陆仟零柒元壹角肆分”)。
  • 4、 零的规则:
    • 阿拉伯数字中间有“0”时,中文大写写“零”(如1010.00 → “人民币壹仟零拾元整”)。
    • 连续多个“0”时,只写一个“零”(如6007.14 → “人民币陆仟零柒元壹角肆分”)。
  • 5、 单位缩写规则:
    • 10写作“拾”,100写作“壹佰”(如110.00 → “人民币壹佰拾元整”)。
    • 十万以上数字接“仟”时不加“零”(如30105000.00 → “人民币叁仟零拾万伍仟元整”)。

温馨提醒: 大家在参加华为OD机试时,切记不要仅仅死记硬背题解代码。真正的通过率取决于你对代码的理解能力。建议你在理解基本原理和逻辑的基础上,模仿并自己编写代码,这样才能更有效地应对机试。

📝2. 输入描述

输入一个double类型数字,表示待转换的金额(0 ≤ 输入 ≤ 1,000,000,000,000)。

🖥️3. 输出描述

输出符合规则的中文大写金额字符串。

🔍4. 示例演示

✨4.1 示例1

输入:

532.00

输出:

人民币伍佰叁拾贰元整

示例说明:

✨4.2 示例2

输入:

6007.14  

输出:

人民币陆仟零柒元壹角肆分

示例说明:

✨4.3 示例3

输入:

99999.99

输出:

人民币玖万玖仟玖佰玖拾玖元玖角玖分

示例说明:

🔑5. 解题分析

🤔5.1 问题理解

题目要求将输入的人民币金额转换为大写中文金额格式。转换的规则包括:

  • 整数部分需要根据单位(元、万、亿等)转换成中文数字。
  • 小数部分需要转换为“角”和“分”,并根据需求处理“整”的情况。
  • 输入金额的范围为 0 < s < 1,000,000,000,000,即最大支持到万亿单位。

核心要求是正确地处理单位、零的去除以及小数部分的转换。

💡5.2 解题思路

  1. 整数部分处理
    • 将整数部分根据单位(亿、万、元等)进行分段转换,每四位一组,单位为“仟”、“佰”、“拾”等。
    • 利用“零”来避免冗余的重复表示(如 1000 需要转为“壹仟”,而 1010 应该转为“壹仟零拾”)。
  2. 小数部分处理
    • 将小数部分分为角和分,分别转换为“角”和“分”。
    • 如果角和分均为零,则输出“整”,否则输出对应的角和分。
  3. 特殊处理
    • 确保处理“零”的规范,避免冗余零(如“零万”应去掉)。
    • 最终组合整数部分和小数部分,输出完整的大写金额。

🎯5.3 问题考点

  • 字符串处理:处理中文数字的转换、字符串拼接与格式化。
  • 大数处理:通过 BigDecimal 处理金额,确保高精度和避免浮点误差。
  • 正则表达式:用于格式化零的处理,确保结果符合规范。
  • 数学运算:通过数学运算将整数部分和小数部分进行分割与转换。

📝5.4 解题步骤

  1. 输入解析:读取输入的金额,并将其转换为 BigDecimal 类型以保证精度。
  2. 整数部分转换:根据单位规则将整数部分转为中文大写。
  3. 小数部分转换:将小数部分(角和分)转换为中文,并处理零的情况。
  4. 拼接结果:将整数部分和小数部分拼接,形成最终的大写金额字符串。
  5. 输出结果:输出转换后的大写金额。

💻6. 解题Coding

根据如上题解思路,进行代码实战,大家请看如下,建议不要死记硬背代码,要理解其题型及实现思路,别担心,代码我都会给出超详细注释,你一定能看明白的。

✅6.1 代码实现

package com.demo.java.OD651_700.OD666;

import java.math.BigDecimal;
import java.util.Scanner;
/**
 * @author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @des: 【人民币转换(B卷-100分)】问题
 * @url: https://blog.csdn.net/weixin_43970743/article/details/148084925
 */
public class OdMain {
        // 数字对应的中文字符
        private static final String[] numberWords = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        // 各个单位,四位一组,分别对应“仟”、“佰”、“拾”和个位
        private static final String[] units = {"仟", "佰", "拾", ""};
        // 更大的单位(亿、万、元)
        private static final String[] bigUnits = {"亿", "万", "元"};

        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            // 读取输入
            String input = scanner.nextLine().trim();
            BigDecimal amount = new BigDecimal(input);
            long integerPart = amount.longValue(); // 获取整数部分
            BigDecimal fractional = amount.remainder(BigDecimal.ONE).multiply(new BigDecimal(100)); // 获取小数部分
            int fractionalPart = fractional.intValue();
            int jiao = fractionalPart / 10; // 获取角
            int fen = fractionalPart % 10; // 获取分

            // 组合结果并输出
            String result = "人民币" + convertIntegerPart(integerPart) + convertFractionalPart(jiao, fen);
            System.out.println(result);
        }

        // 处理整数部分
        private static String convertIntegerPart(long num) {
            if (num == 0) return "零元"; // 如果整数部分为0,直接返回“零元”

            long yi = num / 1_0000_0000L % 1_0000L; // 计算“亿”部分
            long wan = num / 1_0000L % 1_0000L; // 计算“万”部分
            long yuan = num % 1_0000L; // 计算“元”部分
            StringBuilder sb = new StringBuilder();
            boolean needYiZero = false, needWanZero = false;

            if (yi > 0) {
                sb.append(convertFourDigits((int) yi)).append("亿");
                needWanZero = (wan < 1000) && (wan != 0); // 判断“万”部分是否需要补零
            }
            if (wan > 0) {
                if (sb.length() > 0 && (wan < 1000 || needWanZero)) sb.append("零");
                sb.append(convertFourDigits((int) wan)).append("万");
            } else if (yi > 0) {
                needYiZero = true;
            }
            if (yuan > 0 || (yi == 0 && wan == 0)) {
                if ((sb.length() > 0 && (yuan < 1000 || needYiZero)) && yuan != 0) sb.append("零");
                sb.append(convertFourDigits((int) yuan));
            }
            if (sb.length() == 0) sb.append("零"); // 如果没有数字,添加“零”
            sb.append("元");
            return sb.toString().replaceAll("零+", "零").replaceAll("^零|零$", "");
        }

        // 转换四位数
        private static String convertFourDigits(int num) {
            if (num == 0) return "";
            char[] digits = String.format("%04d", num).toCharArray();
            StringBuilder sb = new StringBuilder();
            boolean needZero = false;
            for (int i = 0; i < 4; i++) {
                int digit = digits[i] - '0';
                if (digit != 0) {
                    if (needZero) {
                        sb.append("零");
                        needZero = false;
                    }
                    if (i == 2 && digit == 1) sb.append("拾");
                    else sb.append(numberWords[digit]).append(units[i]);
                } else {
                    for (int j = i + 1; j < 4; j++) {
                        if (digits[j] != '0') {
                            needZero = true;
                            break;
                        }
                    }
                }
            }
            return sb.toString();
        }

        // 处理小数部分
        private static String convertFractionalPart(int jiao, int fen) {
            if (jiao == 0 && fen == 0) return "整"; // 小数部分为0时,输出“整”
            StringBuilder sb = new StringBuilder();
            if (jiao > 0) sb.append(numberWords[jiao]).append("角");
            if (fen > 0) {
                if (jiao == 0) sb.append("零");
                sb.append(numberWords[fen]).append("分");
            }
            return sb.toString();
        }
}

⏱6.2 时间&空间复杂度

  • 时间复杂度O(n),其中 n 是输入金额的位数。由于每次处理四位数,我们的算法在处理整数部分时的复杂度是线性的。
  • 空间复杂度O(1),我们只需要常数级别的额外空间来存储中间结果和最终的转换结果。

⛓‍💥6.3 代码解析

  • main 方法

    • 读取输入的金额并转换为 BigDecimal 以确保精度。
    • 通过 longValue 获取整数部分,并通过 remainder 获取小数部分。然后将整数部分和小数部分分别处理。
    • 最后拼接结果并输出。
  • convertIntegerPart 方法

    • 处理人民币整数部分。通过 StringBuilder 拼接各个部分(亿、万、元)。如果有零,去除冗余零。
    • 例如:35232 会被转为 叁万伍仟贰佰叁拾贰元
  • convertFourDigits 方法

    • 负责将四位数字转换为中文。通过检查每一位数字,按需加上对应的单位(如“仟”、“佰”等)。
  • convertFractionalPart 方法

    • 处理小数部分的转换。将角和分转换为中文格式。如果都为零,则返回“整”。

📝6.4 小结

本题通过递归和字符串拼接的方式,实现了将人民币金额转换为大写中文金额的功能。通过对整数和小数部分的分别处理,解决了中文金额格式的转换问题,避免了冗余零的出现。整个实现流程清晰,代码简洁,容易理解并扩展。

🧪7. 测试用例

🧪7.1 测试用例1

🖥️7.1.1 输入
532.00
🖥️7.1.2 输出
人民币伍佰叁拾贰元整
🖥️7.1.3 实际运行结果展示

根据本地代码进行方法测试,本地运行结果展示如下:

🧪7.2 测试用例2

🖥️7.2.1 输入
6007.14  
🖥️7.2.2 输出
人民币陆仟零柒元壹角肆分
🖥️7.2.3 实际运行结果展示

根据本地代码进行方法测试,本地运行结果展示如下:

🧪7.3 测试用例3

🖥️7.3.1 输入
99999.99
🖥️7.3.2 输出
人民币玖万玖仟玖佰玖拾玖元玖角玖分
🖥️7.3.3 实际运行结果展示

根据本地代码进行方法测试,本地运行结果展示如下:

📥7. 附录源码(Java版)

  针对如上分享OD机试真题之外,这里我还开源全部OD机试原真题源码,供同学们一对一学习!对照每题都有题目号及详细代码注释。Gitee,例如题序号为1,则题解代码对应文件夹OD1,题序号为5,则题解代码对应文件夹OD5,以此类推,目的就是为了方便大家学习,一举上岸!(这里的题序号指专栏导航贴中表格一列的序号)

🧧福利赠与你🧧

  如果你还想学习更多相关OD真题题解,都建议直接毫不犹豫地学习此专栏「最新最全真题华为OD机试真题(全栈版)」,快速掌握Java、Python、C++、JavaScript、Go等多种热门语言详细解题,快速突破华为OD机试,实现350+高分目标。还将提供线上多端答疑交流,解决你的所有问题!

🎁安利其他语言版本题解册🎁

注意: 上述任意专栏一次订阅,获永久免费阅读权限,后续更新都能学习。
声明: 拒绝一切形式的代考,替考行为,务必诚信考试!!!本人所写题库均搜集于互联网。

👩‍💻Who am I?

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主&最具价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

### 华为OD机考数大雁真题及答案解析 #### 题目描述 给定一个字符串 `croakOfFrogs`,表示不同时间点听到的大雁叫声。每只大雁发出的声音序列严格遵循 "quack" 的顺序。返回能够产生所给字符串的最少大雁数量。如果该字符串不是有效的组合,则返回 `-1`。 条件如下: - 输入字符串长度范围:\( 1 \leq croakOfFrogs.length \leq 10^5 \) - 字符串中的字符仅限于 'q', 'u', 'a', 'c' 或者 'k' #### 解决方案 为了计算最小的大雁数量,可以维护五个计数器来跟踪当前正在发声的不同阶段的大雁数目。每当遇到一个新的起始字母(即 'q'),增加相应计数器;当完成一次完整的 “quack” 声音循环时减少这些计数器。还需要确保任何时候后面的字母不会超过前面的字母的数量,否则就不是一个合法的输入[^1]。 下面是具体的实现方法: ```cpp class Solution { public: int minNumberOfGeese(string croakOfGeese) { unordered_map<char, int> count{{'q', 0}, {'u', 0}, {'a', 0}, {'c', 0}, {'k', 0}}; int max_geese = 0; for (char ch : croakOfGeese) { ++count[ch]; // Check the order of characters to ensure validity. if (!(count['q'] >= count['u'] && count['u'] >= count['a'] && count['a'] >= count['c'] && count['c'] >= count['k'])) { return -1; } // Update maximum number of geese at any point in time. max_geese = std::max(max_geese, *std::max_element(count.begin(), count.end(), [](const auto& p1, const auto& p2) { return p1.second < p2.second; })); // When a full sequence is completed ('quack'), decrement all counters by one. if (ch == 'k') { for (auto& pair : count) { --pair.second; } } } // Ensure no incomplete sequences are left over. for (int val : count.values()) { if (val != 0) return -1; } return max_geese; } }; ``` 此代码通过遍历整个字符串并保持对每个声音部的追踪来解决问题。它还验证了每次读取新字符后的合法性,并在检测到完整的一轮发音后重置计数器。最后检查是否有未完成的序列存在,如果有则返回错误码 `-1`,否则返回最大并发大雁数量作为结果[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bug菌¹

你的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值