012.整数转罗马数字
作者:沉默王二 发布时间:2024-01-21T11:32:45.452+0800
鲁迅说过,人生的道路在于不断地积累。每天进步一点点,每天都要有所收获,这样才能够不断地提升自己。从今天开始,刷《二哥的 LeetCode 笔记》吧。
技术派阅读地址:https://paicoding.com/column/7/1 2
-
语雀专栏地址+密码可通过星球置顶帖查看:https://t.zsxq.com/15rEo9Pdu
-
这道题可以说完全重写了,给出1道大家完全都能掌握的题解(贪心算法)。
-
增加代码注释,这样大家更容易看懂并掌握题解;
-
增加参考资料,这样大家可以从零基础直接开刷,减轻新手刷题的阻力;
-
增加手绘图,这样大家更容易理解解题思路;
-
增加 ACM 输入输出,这样大家可以在 Intellij IDEA 中进行调试;
-
增加题解模拟,这样大家可以根据题解模拟整个题解过程,看完会有一种“哦哦”恍然大悟的感觉;
-
图片上传至 OSS 并配合 CDN,提升大家在技术派网站中的阅读体感。
-
另外,这一版本会作为 PDF 的终稿随后在星球进行发布。
题意
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
V 5X 10L 50C 100D 500M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
- I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
- X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
- C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给你一个整数,将其转为罗马数字。
n的范围为1 <= n <= 3999
难度
中等
示例
示例 1:
输入:num=3
示例 2:
输入:num=4
示例 3:
输入:num=9
示例4
输入: num = 58
解释: L = 50, V = 5, III = 3.
示例5
输入: num = 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
分析
从题目的描述中,我们可以得出这样一个结论,罗马数字非常贪心,比如说 4 是 IV,而不是 IIII,9 是 IX,而不是 VIIII,40 是 XL,而不是 XXXX,90 是 XC,而不是 LXXXX,每次都挑最优的算法来表示数字,对吧?
比如说今年是 2024 年,那用罗马数字来表示的话,就先挑最大的 M,也就是 1000,2000 就是 MM,20 就是 XX,24 就是 XXIV,合在一起就是 MMXXIV。
换句话说,每次都用最优解。
这就要引出今天的主角,贪心算法。一种在每一步选择中都采取当前状态下最优的选择(即最“贪心”的选择),以期望最终结果是全局最优的算法。这就是贪心算法的思想。
以找零钱问题为例,假设你是一名售货员,需要给顾客找零钱。你的目标是用最少的货币数量找给顾客相应的零钱。
假设你的货币有 1 元、5 元、10 元、20 元、50 元、100 元这 6 种,需要找给顾客 628 元,你会怎么找呢?
可以先找 100 元,六张;再找 20 元,一张;接着找 5 元,一张;最后找 1 元,三张。
你不可能从 1 元开始找。
整数转罗马数字其实就非常适合贪心算法。题目也告诉我们这样一个对应关系了:
int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
我们用一个 for 循环遍历 values,再用一个 while 循环判断当前数字是否大于等于 values[i],如果是的话,就减去 values[i],并将 values 对应的罗马数字 symbols 添加到结果字符串中。
来看题解:
class Solution {
// 定义两个数组,一个表示特定的罗马数字,一个表示对应的整数值 int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
// 使用 StringBuilder 存储最终的罗马数字字符串 StringBuilder sb = new StringBuilder();
// 遍历整数值数组 for (int i = 0; i < values.length && num > 0; i++) { // 当前数字还大于等于 values[i] 时,继续循环 // 这意味着我们可以从 num 中减去 values[i],并添加对应的罗马数字到结果中 while (num >= values[i]) { num -= values[i]; // 从 num 中减去 values[i] sb.append(symbols[i]); // 添加对应的罗马数字到结果字符串 } }
// 将 StringBuilder 转换为字符串并返回 return sb.toString(); }}
- 定义两个数组:values 和 symbols。values 数组包含了各个罗马数字对应的整数值,而 symbols 数组包含了相应的罗马数字字符串。
- 接着,使用一个 StringBuilder 对象 sb 来构建最终的罗马数字字符串。
- 在主循环中,遍历 values 数组。对于每个元素 values[i],我们检查 num 是否大于或等于 values[i]。
- 如果条件满足,我们就从 num 中减去 values[i],并将相应的罗马数字 symbols[i] 添加到 sb 中。这个过程一直持续到 num 小于当前的 values[i]。
- 这个循环确保了我们总是优先使用最大的罗马数字,直到无法再使用更大的数字为止。
- 最后,将 StringBuilder 对象转换为字符串并返回。
题解效率还不错,击败了 98% 的用户。
总结
本题的关键是通过整数转罗马数字的表象,找出贪心算法的本质。
这种找本质的能力,其实是需要大量的练习才能掌握的。
比如说,还是找零的问题,面值不再是 1 元、2 元、5 元、10 元、20 元、50 元、100 元,而是 1 元、3 元、4 元,要你找零 6 元。
如果是贪心算法,结果会是 1 张 4 元,2 张 1 元。
但更优的选择应该是 2 张 3 元,对吧?
贪心算法的局限性就在于它总是寻求局部最优解,而不一定能得到全局最优解。在每一步,它都做出在当前情况下看起来是最好的决策,而没有考虑这些决策如何影响未来的结果。对于那些局部最优解不等同于全局最优解的问题,贪心算法可能无法得到正确的结果。
其次,这道题涉及到 Java 基础知识就不多了:
力扣链接:https://leetcode.cn/problems/integer-to-roman/
一步一个脚印
不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。
该题解目前只针对**二哥编程星球 **的球友开放,如果你也想一起打卡学习算法的话,扫下面的优惠券加入我们吧,星球目前 4300+ 人,定价 149 元,从当初的 99 元一路涨上来的,所以早就是优势,别再犹豫了。
(优惠券仅 300 张,数量有限)
一个人可以走得很快,但一群人才能走得更远。如果想去面中大厂的话,LeetCode 几乎是必刷的,二哥的 LeetCode 题解通俗易懂、图文并茂,理解给你举一反三的解题能力,冲鸭。
鲁迅说过,人生的道路在于不断地积累。每天进步一点点,每天都要有所收获,这样才能够不断地提升自己。从今天开始,刷《二哥的 LeetCode 笔记》吧。
技术派阅读地址:https://paicoding.com/column/7/1 2
-
语雀专栏地址+密码可通过星球置顶帖查看:https://t.zsxq.com/15rEo9Pdu
-
这道题可以说完全重写了,给出1道大家完全都能掌握的题解(贪心算法)。
-
增加代码注释,这样大家更容易看懂并掌握题解;
-
增加参考资料,这样大家可以从零基础直接开刷,减轻新手刷题的阻力;
-
增加手绘图,这样大家更容易理解解题思路;
-
增加 ACM 输入输出,这样大家可以在 Intellij IDEA 中进行调试;
-
增加题解模拟,这样大家可以根据题解模拟整个题解过程,看完会有一种“哦哦”恍然大悟的感觉;
-
图片上传至 OSS 并配合 CDN,提升大家在技术派网站中的阅读体感。
-
另外,这一版本会作为 PDF 的终稿随后在星球进行发布。
题意
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
V 5X 10L 50C 100D 500M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
- I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
- X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
- C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给你一个整数,将其转为罗马数字。
n的范围为1 <= n <= 3999
难度
中等
示例
示例 1:
输入:num=3
示例 2:
输入:num=4
示例 3:
输入:num=9
示例4
输入: num = 58
解释: L = 50, V = 5, III = 3.
示例5
输入: num = 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
分析
从题目的描述中,我们可以得出这样一个结论,罗马数字非常贪心,比如说 4 是 IV,而不是 IIII,9 是 IX,而不是 VIIII,40 是 XL,而不是 XXXX,90 是 XC,而不是 LXXXX,每次都挑最优的算法来表示数字,对吧?
比如说今年是 2024 年,那用罗马数字来表示的话,就先挑最大的 M,也就是 1000,2000 就是 MM,20 就是 XX,24 就是 XXIV,合在一起就是 MMXXIV。
换句话说,每次都用最优解。
这就要引出今天的主角,贪心算法。一种在每一步选择中都采取当前状态下最优的选择(即最“贪心”的选择),以期望最终结果是全局最优的算法。这就是贪心算法的思想。
以找零钱问题为例,假设你是一名售货员,需要给顾客找零钱。你的目标是用最少的货币数量找给顾客相应的零钱。
假设你的货币有 1 元、5 元、10 元、20 元、50 元、100 元这 6 种,需要找给顾客 628 元,你会怎么找呢?
可以先找 100 元,六张;再找 20 元,一张;接着找 5 元,一张;最后找 1 元,三张。
你不可能从 1 元开始找。
整数转罗马数字其实就非常适合贪心算法。题目也告诉我们这样一个对应关系了:
int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
我们用一个 for 循环遍历 values,再用一个 while 循环判断当前数字是否大于等于 values[i],如果是的话,就减去 values[i],并将 values 对应的罗马数字 symbols 添加到结果字符串中。
来看题解:
class Solution {
// 定义两个数组,一个表示特定的罗马数字,一个表示对应的整数值 int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
// 使用 StringBuilder 存储最终的罗马数字字符串 StringBuilder sb = new StringBuilder();
// 遍历整数值数组 for (int i = 0; i < values.length && num > 0; i++) { // 当前数字还大于等于 values[i] 时,继续循环 // 这意味着我们可以从 num 中减去 values[i],并添加对应的罗马数字到结果中 while (num >= values[i]) { num -= values[i]; // 从 num 中减去 values[i] sb.append(symbols[i]); // 添加对应的罗马数字到结果字符串 } }
// 将 StringBuilder 转换为字符串并返回 return sb.toString(); }}
- 定义两个数组:values 和 symbols。values 数组包含了各个罗马数字对应的整数值,而 symbols 数组包含了相应的罗马数字字符串。
- 接着,使用一个 StringBuilder 对象 sb 来构建最终的罗马数字字符串。
- 在主循环中,遍历 values 数组。对于每个元素 values[i],我们检查 num 是否大于或等于 values[i]。
- 如果条件满足,我们就从 num 中减去 values[i],并将相应的罗马数字 symbols[i] 添加到 sb 中。这个过程一直持续到 num 小于当前的 values[i]。
- 这个循环确保了我们总是优先使用最大的罗马数字,直到无法再使用更大的数字为止。
- 最后,将 StringBuilder 对象转换为字符串并返回。
题解效率还不错,击败了 98% 的用户。
总结
本题的关键是通过整数转罗马数字的表象,找出贪心算法的本质。
这种找本质的能力,其实是需要大量的练习才能掌握的。
比如说,还是找零的问题,面值不再是 1 元、2 元、5 元、10 元、20 元、50 元、100 元,而是 1 元、3 元、4 元,要你找零 6 元。
如果是贪心算法,结果会是 1 张 4 元,2 张 1 元。
但更优的选择应该是 2 张 3 元,对吧?
贪心算法的局限性就在于它总是寻求局部最优解,而不一定能得到全局最优解。在每一步,它都做出在当前情况下看起来是最好的决策,而没有考虑这些决策如何影响未来的结果。对于那些局部最优解不等同于全局最优解的问题,贪心算法可能无法得到正确的结果。
其次,这道题涉及到 Java 基础知识就不多了:
力扣链接:https://leetcode.cn/problems/integer-to-roman/
一步一个脚印
不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。
该题解目前只针对**二哥编程星球 **的球友开放,如果你也想一起打卡学习算法的话,扫下面的优惠券加入我们吧,星球目前 4300+ 人,定价 149 元,从当初的 99 元一路涨上来的,所以早就是优势,别再犹豫了。
(优惠券仅 300 张,数量有限)
一个人可以走得很快,但一群人才能走得更远。如果想去面中大厂的话,LeetCode 几乎是必刷的,二哥的 LeetCode 题解通俗易懂、图文并茂,理解给你举一反三的解题能力,冲鸭。
鲁迅说过,人生的道路在于不断地积累。每天进步一点点,每天都要有所收获,这样才能够不断地提升自己。从今天开始,刷《二哥的 LeetCode 笔记》吧。
技术派阅读地址:https://paicoding.com/column/7/1 2
-
语雀专栏地址+密码可通过星球置顶帖查看:https://t.zsxq.com/15rEo9Pdu
-
这道题可以说完全重写了,给出1道大家完全都能掌握的题解(贪心算法)。
-
增加代码注释,这样大家更容易看懂并掌握题解;
-
增加参考资料,这样大家可以从零基础直接开刷,减轻新手刷题的阻力;
-
增加手绘图,这样大家更容易理解解题思路;
-
增加 ACM 输入输出,这样大家可以在 Intellij IDEA 中进行调试;
-
增加题解模拟,这样大家可以根据题解模拟整个题解过程,看完会有一种“哦哦”恍然大悟的感觉;
-
图片上传至 OSS 并配合 CDN,提升大家在技术派网站中的阅读体感。
-
另外,这一版本会作为 PDF 的终稿随后在星球进行发布。
题意
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
V 5X 10L 50C 100D 500M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
- I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
- X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
- C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给你一个整数,将其转为罗马数字。
n的范围为1 <= n <= 3999
难度
中等
示例
示例 1:
输入:num=3
示例 2:
输入:num=4
示例 3:
输入:num=9
示例4
输入: num = 58
解释: L = 50, V = 5, III = 3.
示例5
输入: num = 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
分析
从题目的描述中,我们可以得出这样一个结论,罗马数字非常贪心,比如说 4 是 IV,而不是 IIII,9 是 IX,而不是 VIIII,40 是 XL,而不是 XXXX,90 是 XC,而不是 LXXXX,每次都挑最优的算法来表示数字,对吧?
比如说今年是 2024 年,那用罗马数字来表示的话,就先挑最大的 M,也就是 1000,2000 就是 MM,20 就是 XX,24 就是 XXIV,合在一起就是 MMXXIV。
换句话说,每次都用最优解。
这就要引出今天的主角,贪心算法。一种在每一步选择中都采取当前状态下最优的选择(即最“贪心”的选择),以期望最终结果是全局最优的算法。这就是贪心算法的思想。
以找零钱问题为例,假设你是一名售货员,需要给顾客找零钱。你的目标是用最少的货币数量找给顾客相应的零钱。
假设你的货币有 1 元、5 元、10 元、20 元、50 元、100 元这 6 种,需要找给顾客 628 元,你会怎么找呢?
可以先找 100 元,六张;再找 20 元,一张;接着找 5 元,一张;最后找 1 元,三张。
你不可能从 1 元开始找。
整数转罗马数字其实就非常适合贪心算法。题目也告诉我们这样一个对应关系了:
int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
我们用一个 for 循环遍历 values,再用一个 while 循环判断当前数字是否大于等于 values[i],如果是的话,就减去 values[i],并将 values 对应的罗马数字 symbols 添加到结果字符串中。
来看题解:
class Solution {
// 定义两个数组,一个表示特定的罗马数字,一个表示对应的整数值 int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
// 使用 StringBuilder 存储最终的罗马数字字符串 StringBuilder sb = new StringBuilder();
// 遍历整数值数组 for (int i = 0; i < values.length && num > 0; i++) { // 当前数字还大于等于 values[i] 时,继续循环 // 这意味着我们可以从 num 中减去 values[i],并添加对应的罗马数字到结果中 while (num >= values[i]) { num -= values[i]; // 从 num 中减去 values[i] sb.append(symbols[i]); // 添加对应的罗马数字到结果字符串 } }
// 将 StringBuilder 转换为字符串并返回 return sb.toString(); }}
- 定义两个数组:values 和 symbols。values 数组包含了各个罗马数字对应的整数值,而 symbols 数组包含了相应的罗马数字字符串。
- 接着,使用一个 StringBuilder 对象 sb 来构建最终的罗马数字字符串。
- 在主循环中,遍历 values 数组。对于每个元素 values[i],我们检查 num 是否大于或等于 values[i]。
- 如果条件满足,我们就从 num 中减去 values[i],并将相应的罗马数字 symbols[i] 添加到 sb 中。这个过程一直持续到 num 小于当前的 values[i]。
- 这个循环确保了我们总是优先使用最大的罗马数字,直到无法再使用更大的数字为止。
- 最后,将 StringBuilder 对象转换为字符串并返回。
题解效率还不错,击败了 98% 的用户。
总结
本题的关键是通过整数转罗马数字的表象,找出贪心算法的本质。
这种找本质的能力,其实是需要大量的练习才能掌握的。
比如说,还是找零的问题,面值不再是 1 元、2 元、5 元、10 元、20 元、50 元、100 元,而是 1 元、3 元、4 元,要你找零 6 元。
如果是贪心算法,结果会是 1 张 4 元,2 张 1 元。
但更优的选择应该是 2 张 3 元,对吧?
贪心算法的局限性就在于它总是寻求局部最优解,而不一定能得到全局最优解。在每一步,它都做出在当前情况下看起来是最好的决策,而没有考虑这些决策如何影响未来的结果。对于那些局部最优解不等同于全局最优解的问题,贪心算法可能无法得到正确的结果。
其次,这道题涉及到 Java 基础知识就不多了:
力扣链接:https://leetcode.cn/problems/integer-to-roman/
一步一个脚印
不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。
该题解目前只针对**二哥编程星球 **的球友开放,如果你也想一起打卡学习算法的话,扫下面的优惠券加入我们吧,星球目前 4300+ 人,定价 149 元,从当初的 99 元一路涨上来的,所以早就是优势,别再犹豫了。
(优惠券仅 300 张,数量有限)
一个人可以走得很快,但一群人才能走得更远。如果想去面中大厂的话,LeetCode 几乎是必刷的,二哥的 LeetCode 题解通俗易懂、图文并茂,理解给你举一反三的解题能力,冲鸭。
知识星球
扫码加入星球
查看更多优质内容
https://wx.zsxq.com/mweb/views/joingroup/join_group.html?group_id=15522885221412