해석과 풀이는 개인적인 부분이기 때문에 참고만 하시길 바랍니다. 다른 접근 및 풀이는 언제나 환영합니다. 댓글로 남겨주세요.
1. 문제
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.
2. 해석
로마숫자가 주어질 때 이를 아라비안 숫자로 변경하면 된다.
단, IV는 4, IX는 9, XL는 40, XC는 90, CD는 400, CM은 900을 가르킨다.
3. 풀이
- 나는 항상 단순 무식하게 접근하는 편이라 ㅠㅠ
① 첫번째 map에는 일반 로마숫자를 담아두고
② 두번째 map에는 예외되는 4, 9, 40, 90, 400, 900에 해당되는 로마숫자를 담는다.
③ 문제로 주어진 문자 s(로마숫자)를 두번째 map부터 비교를 하여 값을 계산하고, 비교했던 로마숫자는 주어진 문자 s에서 제거해둔다.
④ 남은 문자 s는 for문 이용해 첫번째 map의 로마자와 비교하여 ③번에 계산된 값에 마저 더한다.
* Map의 특징
Map은 인터페이스이므로 Map 유형의 객체를 만들 수 없다. 객체를 생성하려면 Map을 확장하는 클래스가 필요하다. Map은 중복 키를 허용하지 않으며 TreeMap과 LinkedHashMap은 순서를 유지하나 HashMap은 유지하지 않는다.
class Solution {
public int romanToInt(String s) {
int total = 0;
// 첫번째 map
Map<String, Integer> m = new HashMap<String, Integer>();
m.put("I", 1);
m.put("V", 5);
m.put("X", 10);
m.put("L", 50);
m.put("C", 100);
m.put("D", 500);
m.put("M", 1000);
// 두번째 map
Map<String, Integer> p = new HashMap<String, Integer>();
p.put("IV", 4);
p.put("IX", 9);
p.put("XL", 40);
p.put("XC", 90);
p.put("CD", 400);
p.put("CM", 900);
// 4,9,40,90,400,900에 해당되는 로마자를 먼저 확인 후 계산
for(Map.Entry<String, Integer> map : p.entrySet()) {
if(s.indexOf(map.getKey()) != -1) {
total += map.getValue();
s = s.replace(map.getKey(), ""); // 비교한 로마자는 제거
}
}
// 남은 로마자를 첫번째 map에 있는지 확인 후 계산
for(int i=0; i<s.length(); i++) {
String key = s.substring(i, i+1);
if(m.containsKey(key)) {
int value = m.get(key);
total += value;
}
}
return total;
}
}
4. LeetCoder의 접근 및 풀이
- 역시 고수는 달랐다ㅠㅠ 코드길이가 나의 ⅓ 수준이다.
- 힌트는 문제에 있었다.
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:
로마 숫자는 일반적으로 왼쪽에서 오른쪽으로 가장 큰 숫자부터 가장 작은 숫자로 기록된다. 하지만 4의 숫자는 IIII가 아니다. 대신 숫자 4를 IV로 쓴다. 1이 5보다 앞에 있기 때문에 그것을 빼면 4가 된다. 같은 원리가 IX로 쓰여진 숫자 9에도 적용됩니다. 뺄셈이 사용되는 경우는 6가지가 있다.
-> 대놓고 뺄셈 얘기를 했다. 예를 들면 로마자(IV)가 나올경우 로마자의 앞(I)이 뒤(V)보다 작을 경우 뒤에서 앞을 빼면 된다!!!
class Solution {
public int romanToInt(String s) {
int ans = 0, num = 0;
// 로마자를 뒤에서부터 읽는 for문 사용
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 (num < ans)
ans -= num;
else
ans += num;
}
return ans;
}
}
- 고수의 코드를 접하고 나의 코드를 보니 만약 더 큰 로마자가 나올 경우 올바르게 읽지 못하는 오류 가능성이 있어 보인다.ㅠㅠ
'Coding Test' 카테고리의 다른 글
[String] 01.문자 찾기 (2) | 2023.12.29 |
---|---|
[LeetCode - Easy] 20. Valid Parentheses (0) | 2023.09.07 |
[LeetCode - Easy] 14. Longest Common Prefix (0) | 2023.09.02 |
[LeetCode - Easy] 9. Palindrome Number (0) | 2023.08.31 |
[LeetCode - Easy] 1. Two Sum (0) | 2023.08.30 |