LeetCode题练习与总结:整数转换英文表示--273
一、题目描述
将非负整数 num
转换为其对应的英文表示。
示例 1:
输入:num = 123 输出:"One Hundred Twenty Three"
示例 2:
输入:num = 12345 输出:"Twelve Thousand Three Hundred Forty Five"
示例 3:
输入:num = 1234567 输出:"One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven"
提示:
0 <= num <= 2^31 - 1
二、解题思路
- 首先定义小于20的数字和10的倍数的英文表示,因为它们的表示是特殊的(例如,10是"Ten",11是"Eleven")。
- 定义一个方法,用于处理小于1000的数字,因为这个范围内的数字表示有一定的规律性(例如,123是"One Hundred Twenty Three")。
- 由于英文数字表示中,每三位数就会有一个单位(例如,“Billion”, “Million”, “Thousand”),我们可以按照每三位一组的方式,将数字拆分成多个小组。
- 对于每个小组,使用步骤2定义的方法来转换成英文表示,并加上对应的单位。
- 将所有小组的英文表示拼接起来,得到最终结果。
三、具体代码
class Solution {private static final String[] LESS_THAN_20 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};private static final String[] TENS = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};private static final String[] THOUSANDS = {"", "Thousand", "Million", "Billion"};public String numberToWords(int num) {if (num == 0) return "Zero";StringBuilder sb = new StringBuilder();for (int i = 3, unit = 1000000000; i >= 0; i--, unit /= 1000) {int curNum = num / unit;if (curNum != 0) {num -= curNum * unit;sb.append(helper(curNum)).append(THOUSANDS[i]).append(" ");}}return sb.toString().trim();}private String helper(int num) {if (num == 0) {return "";} else if (num < 20) {return LESS_THAN_20[num] + " ";} else if (num < 100) {return TENS[num / 10] + " " + helper(num % 10);} else {return LESS_THAN_20[num / 100] + " Hundred " + helper(num % 100);}}
}
在这段代码中,numberToWords
方法负责将数字拆分成多个三位数的组,并调用 helper
方法将每个组转换成英文表示。helper
方法则根据数字的大小,递归地将其转换成英文表示。
四、时间复杂度和空间复杂度
1. 时间复杂度
numberToWords
方法中有一个for循环,该循环会最多执行4次(对应于" Billion", “Million”, “Thousand”, "None"这些单位)。每次循环中,都会调用helper
方法。helper
方法是一个递归方法,但是它的递归深度最多为3(对于小于1000的数字,递归会停在个位数上)。这是因为每次递归都会将数字缩小到原来的1/10或者1/100。- 因此,
helper
方法的调用次数是常数次的(最多3次)。 - 综上所述,时间复杂度是O(1),即常数时间复杂度。尽管我们有一个循环,但由于循环次数和递归深度都是固定的,因此总体的操作次数是有限的,不随输入数字的大小而变化。
2. 空间复杂度
LESS_THAN_20
,TENS
,THOUSANDS
这三个字符串数组占用的空间是固定的,不随输入数字的大小而变化。numberToWords
方法中使用了StringBuilder
来构建结果字符串。在最坏的情况下,即数字接近2^31 - 1时,StringBuilder
的长度可能会达到几十个字符,但这也是一个常数级别的空间。helper
方法是递归调用的,每次递归调用都会在调用栈上占用一定的空间。由于递归深度最多为3,因此调用栈的空间占用也是常数级别的。- 综上所述,空间复杂度是O(1),即常数空间复杂度。尽管使用了递归,但由于递归深度固定,因此总体的空间占用是有限的,不随输入数字的大小而变化。
五、总结知识点
-
静态常量数组:
LESS_THAN_20
,TENS
,THOUSANDS
是静态常量数组,用于存储数字的英文表示。它们在类加载时初始化,并在整个程序运行期间保持不变。 -
递归方法:
helper
方法是一个递归方法,它用于将小于1000的数字转换成英文表示。递归方法在解决能够分解成更小相似问题的场景中非常有用。 -
字符串拼接:在
helper
方法中,字符串是通过+
运算符拼接的。这是处理字符串常用的方法之一。 -
StringBuilder 类:在
numberToWords
方法中,使用了StringBuilder
类来构建最终的英文数字表示。StringBuilder
在处理频繁修改字符串的场景中比直接使用字符串拼接更高效。 -
数学运算:代码中使用了整数除法和取余操作来将数字拆分成不同的部分(如百位、十位、个位)。
-
循环控制:
numberToWords
方法中使用了一个for循环来处理数字的每个千位分组(Billion, Million, Thousand, None)。循环中的i
变量用来索引THOUSANDS
数组,而unit
变量用来确定当前处理的千位分组的大小。 -
条件语句:在
helper
方法中,使用了if-else语句来根据数字的大小选择不同的处理逻辑。 -
字符串处理:在返回结果之前,使用了
trim()
方法来移除字符串末尾的空格。 -
边界条件处理:在
numberToWords
方法开始时,如果输入数字为0,则直接返回 “Zero”,这是对特殊情况的处理。 -
模块化设计:代码被设计成模块化的,
helper
方法负责处理小于1000的数字,而numberToWords
方法则负责处理更大范围的数字,这种设计使得代码易于理解和维护。 -
面向对象编程:整个解决方案被封装在一个
Solution
类中,这是一种面向对象编程的实践,有助于代码的组织和重用。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。