문제
Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
For example, 2 is written as II in Roman numeral, just two ones added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:
- I can be placed before V (5) and X (10) to make 4 and 9.
- X can be placed before L (50) and C (100) to make 40 and 90.
- C can be placed before D (500) and M (1000) to make 400 and 900.
Given a roman numeral, convert it to an integer.
Example 1:
Input: s = "III"
Output: 3
Explanation: III = 3.
Example 2:
Input: s = "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.
Example 3:
Input: s = "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
정답 코드
< 내 정답 코드 >
class Solution {
private enum RomeNum {
I(1), V(5), X(10), L(50), C(100), D(500), M(1000);
private int value;
private RomeNum(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public static int romanToInt(String s) {
int sum = 0;
int length = s.length();
int idx = 0;
while (idx < length) {
String nums = "";
char ch = s.charAt(idx);
if (idx + 1 < length) {
nums = s.substring(idx, idx + 2);
}
if (nums.equals("IV")) {
sum += 4;
idx += 2;
continue;
} else if (nums.equals("IX")) {
sum += 9;
idx += 2;
continue;
} else if (nums.equals("XL")) {
sum += 40;
idx += 2;
continue;
} else if (nums.equals("XC")) {
sum += 90;
idx += 2;
continue;
} else if (nums.equals("CD")) {
sum += 400;
idx += 2;
continue;
} else if (nums.equals("CM")) {
sum += 900;
idx += 2;
continue;
}
sum += RomeNum.valueOf(String.valueOf(ch)).getValue();
idx++;
}
return sum;
}
}
< 타인 답변 코드 1 >
public class RomantoInteger13 {
public int romanToInt(String s) {
Map<Character, Integer> map = new HashMap<>();
map.put('I', 1);
map.put('V', 5);
map.put('X', 10);
map.put('L', 50);
map.put('C', 100);
map.put('D', 500);
map.put('M', 1000);
int sum = 0;
for (int i = 0; i < s.length(); i++) {
if (i > 0 && map.get(s.charAt(i)) > map.get(s.charAt(i - 1))) {
sum += map.get(s.charAt(i)) - (2 * map.get(s.charAt(i - 1)));
} else {
sum += map.get(s.charAt(i));
}
}
return sum;
}
}
< 타인 답변 코드 2 >
class Problem4 {
public static int romanToInt(String s) {
int ans = 0;
int num = 0;
for (int i = s.length() - 1; i >= 0; i--) {
switch (s.charAt(i)) {
case 'I':
num = 1;
break;
case 'V':
num = 5;
break;
case 'X':
num = 10;
break;
case 'L':
num = 50;
break;
case 'C':
num = 100;
break;
case 'D':
num = 500;
break;
case 'M':
num = 1000;
break;
}
if (4 * num < ans) {
ans -= num;
} else {
ans += num;
}
}
return ans;
}
}
이것을 주의하자!
- 주어진 라틴어 기호에 따라서 제공되는 값은 enum 을 사용했다. 며칠 전 enum 사용법을 익혔는데 여기서 활용했다.
- 이 문제의 핵심은 불규칙한 패턴을 어떻게 처리하냐에 있다. 특히 IV , IX , XL , XC , CD , CM 기호는 별도의 값으로 처리해야 했기 때문에 이 부분이 고민이 많았다. 분명 딱 떨어지는 공식이 있을 것 같았지만 결국엔 string.substring( ) 을 이용해서 해당 기호와 일치하면 별도의 값으로 처리하게 작성했다. 개인적으로 마음에 안 들지만 일단 기능이 동작하도록 만들었다. 반복적인 if 문 없이도 주어진 String 문자열에서 특정 패턴만 골라낼 수 있을까??
- 타인 답변 코드 1을 보면 HashMap 으로 구현했다. 그리고 특이 패턴을 처리한 방식은 "앞의 문자가 뒤의 문자보다 '작으면'!! " 이란 특성을 이용했다.
- 타인 답변 코드 2를 보면 Switch 문으로 작성했다. 특이 패턴 처리 방식은 맨 뒷 요소부터 하나씩 꺼낸 후 크기 비교를 통해 구분했다. (사실 이 코드는 아직도 이해가 안 된다...ㅎㅎ)
- 내 코드는 정말 원시적이다. 이런 문제와 만났을 땐 일정한 '패턴'을 발견하는 것이 중요하다. 즉 "앞의 문자가 뒤의 문자보다 작은 경우가 특이 패턴!" 과 같이 규칙이 있기 마련이다. 침착하게 발견해보자.
'코딩 테스트' 카테고리의 다른 글
[LeetCode] (Easy) Longest Common Prefix (0) | 2022.11.24 |
---|---|
[LeetCode] (Easy) Palindrome Number (0) | 2022.11.23 |
[LeetCode] (Medium) Reverse Integer * (0) | 2022.11.23 |
[LeetCode] (Easy) Two Sum ** (0) | 2022.11.23 |
[Hacker Rank] (Easy) Time Conversion (0) | 2022.11.20 |