七个不同的符号代表罗马数字,其值如下:

符号
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:

  1. 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
  2. 如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。
  3. 只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式。
给定一个整数,将其转换为罗马数字。  

示例 1:
输入:num = 3749
输出: "MMMDCCXLIX"

解释:
3000 = MMM 由于 1000 (M) + 1000 (M) + 1000 (M)
700 = DCC 由于 500 (D) + 100 (C) + 100 (C)
40 = XL 由于 50 (L) 减 10 (X)
9 = IX 由于 10 (X) 减 1 (I)
注意:49 不是 50 (L) 减 1 (I) 因为转换是基于小数位

示例 2:
输入:num = 58
输出:"LVIII"

解释:
50 = L
8 = VIII

示例 3:
输入:num = 1994
输出:"MCMXCIV"

解释:
1000 = M
900 = CM
90 = XC
4 = IV

提示: 1 <= num <= 3999

解题思路

拿到这道题,脑海里有个大概的思路,就是将数字上的每一位数字都用对应的字符来表示,那么问题就转换成求出每一位的数字,大概思路,就是用num对1000 ,100, 10进行除法和求模,除法的作用是获取当前最高位的数字,求模是获取去除最高位数字之后的数字。
然后要做的事情就是将对应位上的数字按照规则格式化成对应的字符

代码

var intToRoman = function(num) {
let restNumber = 0
let result = ''

//根据数字不同生成不同的字符
function generateStr(oneStr, fiveStr, tenStr, count) {
let r = ''

if (count < 5) {
if (count === 4) {
return `${oneStr}${fiveStr}`
}else {
for (let i = 0; i < count; i++) {
r += oneStr
}
}
}else {
if (count === 9) {
return `${oneStr}${tenStr}`
}else {
r = fiveStr
for (let i = 5; i < count; i++) {
r += oneStr
}
}
}
return r
}


//获取千位上的字符
const thousand = Math.floor(num / 1000)
restNumber = num % 1000
result = generateStr('M', '', '' ,thousand)

//获取百位上的字符
const hundred = Math.floor(restNumber / 100)
restNumber = restNumber % 100
result += generateStr('C', 'D', 'M', hundred)

//获取十位上的字符
const ten = Math.floor(restNumber / 10)
const v = restNumber % 10
result += generateStr('X', 'L', 'C', ten)

//获取个位上的字符
result += generateStr('I', 'V', 'X', v)

return result
};

感觉很完美,提交一看结果只超过50%的人。what! emmm…..

回过头来看,其实我们在求每个位上的数字的操作可以和生成字符组合起来。

比如3000,之前的操作:

  1. 3000 / 1000 = 3
  2. 然后循环3次生成3个M

可以改成:

  1. 3000 - 1000 = 2000 生成一个M
  2. 2000 - 1000 = 1000 生成一个M
  3. 1000 - 1000 = 0 生成一个M

我们不用特地求出每个位上的数字,再去生成,而是通过不断的减法,完成字符的生成。这里需要注意的点就是可以提前把900,400,90,40,9,4的字符生成好,不用特地去判断是否是4或者9,只要能够减去4或者9就代表能生成

代码:

var intToRoman = function(num) {
let result = ''

const numberArr = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
const charArr = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']

for (let i = 0; i < numberArr.length; i++) {
while (num >= numberArr[i]) {
num -= numberArr[i]
result += charArr[i]
}
}

return result
};