[LeetCode] 13. Roman to Integer

강성준·2024년 5월 7일

LeetCode 문제풀이

목록 보기
1/2

📒문제

로마 숫자는 I, V, X, L, C, D, M 7가지 기호로 표시됩니다.
로마 숫자가 주어지면 이를 정수로 변환합니다.

SymbolValue
I1
V5
X10
L50
C100
D500
M1000
일반적으로 로마 숫자는 왼쪽에서 오른쪽으로 가장 큰 숫자부터 가장 작은 숫자로 기록됩니다.

하지만 그렇지 않은 경우도 있습니다.
* I를 V와 X 앞에 배치하여 4와 9를 만들 수 있습니다.
* X를 L와 C 앞에 배치하여 40와 90를 만들 수 있습니다.
* C를 D와 M 앞에 배치하여 400와 900를 만들 수 있습니다.

😆풀이

문제를 살펴보면 로마 숫자는 7개로 이루어져있다고 하지만, 아래에 6가지의 수가 더 존재한다.

* I를 V와 X 앞에 배치하여 4와 9를 만들 수 있습니다.
* X를 L와 C 앞에 배치하여 40와 90를 만들 수 있습니다.
* C를 D와 M 앞에 배치하여 400와 900를 만들 수 있습니다.

이 부분이 없다면 문자로 들어온 로마 숫자를 한 글자씩 쪼개어 하나의
int형 변수에 누적 시키면 쉽게 문제를 풀 수 있다.
하지만 해당 부분이 문제에 포함 되어있으니 이 부분도 처리해줘야한다.

문제를 보면서 SymbolValue로 이루어진것을 보고 Map이 떠올랐다.
MapKeyValue로 저장해두고 로마 숫자를 쪼개어 Map을 순회하며 탐색하고 Map에 맞는 Key가 있다면 int형 변수에 누적시키는 방법을 떠올렸다.

먼저 경우의 수를 전부 Map에 저장하였다.

Map<String, Integer> romanMap = new HashMap<>();
        
romanMap.put("I", 1);
romanMap.put("IV", 4);
romanMap.put("V", 5);
romanMap.put("IX", 9);
romanMap.put("X", 10);
romanMap.put("XL", 40);
romanMap.put("L", 50);
romanMap.put("XC", 90);
romanMap.put("C", 100);
romanMap.put("CD", 400);
romanMap.put("D", 500);
romanMap.put("CM", 900);
romanMap.put("M", 1000);

그 다음엔 반복을 통해 문자열로 들어온 로마 숫자를 검사한다.

int answer = 0;
        
for(int i = 0; i < s.length();) {
	// 두 글자씩 검사하기 위해
    String twoChSubStr = s.substring(i, Math.min(s.length(), i + 2));
    // 한 글자씩 검사하기 위해
    String oneChSubStr = s.substring(i, i + 1);
            
    // 두 글자에 해당되는 key가 map에 있다면
    if(romanMap.containsKey(twoChSubStr)) {
    	// answer 변수에 누적하여 더함
    	answer += romanMap.get(twoChSubStr);
    	// 두 글자에 해당하는 숫자기 때문에 인덱스를 2 증가 시켜줌
    	i += 2;
	} else { // 두 글자에 해당되는 key가 없는 경우(한 글자 숫자인 경우)
    	// 한 글자에 해당되는 Key의 value를 answer 변수에 누적하여 더함
    	answer += romanMap.get(oneChSubStr);
        // 한 글자에 해당되기 때문에 인덱스는 하나 올려줌
        i++;
	}
}
        
return answer;

한 글자, 두 글자에 대한 부분에 대한 처리가 각각 있어야 하기 때문에
oneChSubStr, twoChSubStr 변수를 각각 선언하였다.

반복문에서 i 변수에 대한 증감식을 처리하지 않았다. 그 이유는 반복이 될때 증가하는 것이 아닌 경우에 따라 증가하는 양이 다르기 때문이다.

// 두 글자씩 검사하기 위해
String twoChSubStr = s.substring(i, Math.min(s.length(), i + 2));
// 한 글자씩 검사하기 위해
String oneChSubStr = s.substring(i, i + 1);

이 부분을 주목하자 여기서 substring을 이용해 문자열을 잘라내어 저장한다.

twoChSubStri부터 Math.min(s.length(), i + 2)까지 잘라내어 저장한다.

s의 길이가 4이고 i가 0이라면 0부터 4 or i+2 까지 잘라내게 된다.
i가 0이라고 가정했을때 4와 i+2중 작은것은 i+2이기 때문에 i+2 = 2까지가 범위로 0부터 2까지 잘려 저장된다.

만약 s의 길이가 4이고 i도 4인 경우라면 i+2는 6이기 때문에 s.length만큼까지만 잘라내질 것이다.

그 이후의 처리는 아래 조건문에서 처리된다.

// 두 글자에 해당되는 key가 map에 있다면
if(romanMap.containsKey(twoChSubStr)) {
	// answer 변수에 누적하여 더함
	answer += romanMap.get(twoChSubStr);
    // 두 글자에 해당하는 숫자기 때문에 인덱스를 2 증가 시켜줌
    i += 2;
} else {
	// 두 글자에 해당되는 key가 없는 경우(한 글자 숫자인 경우)
    // 한 글자에 해당되는 Key의 value를 answer 변수에 누적하여 더함
    answer += romanMap.get(oneChSubStr);
    // 한 글자에 해당되기 때문에 인덱스는 하나 올려줌
    i++;
}

잘라낸 두 글자용 문자열이 romanMap에 저장된 key로 된 데이터가 존재하는지 검사하고 그것이 아니라면 한글자에 해당된다는 것이기 때문에 위와 같이 처리할 수 있다.

여기서 또한 인덱스로 쓰이는 i에 대한 처리도 함께 하는데 두글자에 해당된다면 i는 두글자만큼 가야하고 한글자인 경우 한 글자만큼만 증가하면 되기 때문이다.

profile
Java, Spring Framework로 백엔드 개발을 하는 개발자입니다.

0개의 댓글