[리트코드] 12. Integer to Roman
안녕하세요. 개발조각입니다.😊
이번 문제는 어려운 건 아닌데... 머리를 굴려야 해결할 수 있어서 푸는데 좀 오래 걸렸어요ㅠ
https://leetcode.com/problems/integer-to-roman/submissions/
Integer to Roman - LeetCode
Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.
leetcode.com
해결방안
var intToRoman = function(num) {
let roma = {1:'I', 5:'V', 10:'X', 50:'L', 100:'C', 500:'D', 1000:'M'};
let romaNum = '';
let strArr = String(num).split('');
let numArr = strArr.map((x, i)=> parseInt(x)*(10**(strArr.length-i-1))).reverse();
console.log(numArr)
for(let i=0; i<numArr.length; i++){
let num = numArr[i];
let isRoma = roma[num];
if(isRoma) romaNum = isRoma+romaNum;
else{
let str = '';
let [one, five, ten] = [i ? 10**(i-1)*10 : 1, 10**(i)*5, 10**(i+1)]
let [roma1, roma5, roma10] = [roma[one], roma[five], roma[ten]];
if(ten-num === 10**i) str = roma1+roma10;
else if(num-five === -(10**i)) str = roma1+roma5;
else if(num > five){
let remainder = (num - five)/one;
str = roma5+roma1.repeat(remainder);
}
else if(num < five){
let remainder = num/one;
str = roma1.repeat(remainder);
}
romaNum = str+romaNum;
}
}
return romaNum;
};
기존에 생각했던 해결방안입니다.
let roma = {1:'I', 5:'V', 10:'X', 50:'L', 100:'C', 500:'D', 1000:'M'};
먼저 1, 5, 10, 50, 100, 500, 1000에 대한 각각에 해당되는 로마 숫자를 대입해주었습니다.
let strArr = String(num).split('');
let numArr = strArr.map((x, i)=> parseInt(x)*(10**(strArr.length-i-1))).reverse();
만약 num = 1994 일 경우 numArr = [4, 90, 900, 1000]으로 바꾸면 뒤에 반복문 돌리면서
각각의 로마 숫자 구하기 쉬워질 것 같아서 바꾸어 보았습니다.
let num = numArr[i];
let isRoma = roma[num];
if(isRoma) romaNum += isRoma;
roma배열에 있는 숫자인 경우에 대한 코드입니다.
isRoma는 roma객체에 해당하는 값이 있으면 로마 숫자로 반환해 줍니다.
else{
let str = '';
let [one, five, ten] = [i ? 10**(i-1)*10 : 1, 10**(i)*5, 10**(i+1)]
let [roma1, roma5, roma10] = [roma[one], roma[five], roma[ten]];
if(ten-num === 10**i) str = roma1+roma10;
else if(num-five === -(10**i)) str = roma1+roma5;
else if(num > five){
let remainder = (num - five)/one;
str = roma5+roma1.repeat(remainder);
}
else if(num < five){
let remainder = num/one;
str = roma1.repeat(remainder);
}
romaNum = str+romaNum;
}
roma배열에 있는 숫자가 아닌 다른 숫자일 경우에 대한 코드입니다.
여기서는 4가지로 구분하였습니다.
- 9, 90, 900일 경우
- 4, 40, 400일 경우
- 6~8, 60~80, 600~800일 경우
- 1~3, 10~30, 100~300일 경우
4가지는 if else로 구하였습니다.
let [one, five, ten] = [i ? 10**(i-1)*10 : 1, 10**(i)*5, 10**(i+1)]
let [roma1, roma5, roma10] = [roma[one], roma[five], roma[ten]];
one, five, ten은 해당 위치에 가까운 숫자? 라 해야 될까요.
만약 num=30이면 one=10, five=50, ten=100이 됩니다.
one에서는 만약 num이 한자리 수면 1을 반완해야 되기 때문에 삼항 연산자로 해주었습니다.
roma1, roma5, roma10은 위에 one, five, ten의 값에 대한 로마 숫자입니다.
이렇게
- 9, 90, 900일 경우
- 4, 40, 400일 경우
이 2가지를 각각 다 구해도 되지만 roma배열에 미리 써두는 것도 좋은 방법입니다.
let roma = {1:'I', 4:'IV', 5:'V', 9:'IX', 10:'X', 40:'XL', 50:'L', 90:'XC', 100:'C', 400:'CD', 500:'D', 900:'CM', 1000:'M'};
이렇게요.
위와 같이 roma배열에 더 추가할 경우 바뀐 코드입니다.
var intToRoman = function(num) {
let roma = {1:'I', 4:'IV', 5:'V', 9:'IX', 10:'X', 40:'XL', 50:'L', 90:'XC', 100:'C', 400:'CD', 500:'D', 900:'CM', 1000:'M'};
let romaNum = '';
let strArr = String(num).split('');
let numArr = strArr.map((x, i)=> parseInt(x)*(10**(strArr.length-i-1))).reverse();
for(let i=0; i<numArr.length; i++){
let num = numArr[i];
let isRoma = roma[num];
if(isRoma) romaNum = isRoma+romaNum;
else{
let str = '';
let [one, five] = [i ? 10**(i-1)*10 : 1, 10**(i)*5];
let [roma1, roma5] = [roma[one], roma[five]];
if(num > five){
let remainder = (num - five)/one;
str = roma5+roma1.repeat(remainder);
}
else if(num < five){
let remainder = num/one;
str = roma1.repeat(remainder);
}
romaNum = str+romaNum;
}
}
return romaNum;
};
이렇게 되면
if(ten-num === 10**i) str = roma1+roma10;
else if(num-five === -(10**i)) str = roma1+roma5;
이걸 안 써도 되고
let [one, five, ten] = [i ? 10**(i-1)*10 : 1, 10**(i)*5, 10**(i+1)]
let [roma1, roma5, roma10] = [roma[one], roma[five], roma[ten]];
ten, roma10도 필요 없게 됩니다.