Published on

LeetCode - Roman to Integer (13)

Authors
  • avatar
    Name
    devnmin
    Twitter

Intuition

문제링크: https://leetcode.com/problems/roman-to-integer/description/

로마 숫자는 보통 왼쪽에서 오른쪽으로 값을 더하는 방식이지만,
특정 조합(예: IV, IX)은 앞 문자의 값이 더 작을 경우 감산해야 합니다.
이러한 특이 케이스들을 먼저 처리해주는 방식이 떠올랐습니다.


Approach

  • 일반 문자(I, V, X 등)의 값은 미리 딕셔너리로 매핑
  • 특수한 2글자 조합(IV, IX, CM 등)은 별도로 저장
  • 반복문에서 문자열을 순회하면서 2글자 조합이 있는 경우 먼저 확인
  • 있으면 해당 값을 더하고 인덱스를 2칸 이동, 없으면 1글자만 처리

Complexity

  • Time complexity: O(n)O(n)
    (문자열 길이 n만큼 한 번씩 순회)

  • Space complexity: O(1)O(1)
    (고정된 딕셔너리와 상수 메모리만 사용)


Code (내 풀이)

mapping_values = {
    "I": 1,
    "V": 5,
    "X": 10,
    "L": 50,
    "C": 100,
    "D": 500,
    "M": 1000,
}
matching_patterns = {
    "IV": 4,
    "IX": 9,
    "XL": 40,
    "XC": 90,
    "CD": 400,
    "CM": 900,
}


class Solution:
    def romanToInt(self, s: str) -> int:
        sum = 0
        i = 0
        while i < len(s):
            is_set = False
            if i != len(s) - 1:
                for matching_pattern in matching_patterns:
                    if matching_pattern == s[i : i + 2]:
                        sum += matching_patterns[s[i : i + 2]]
                        i += 1
                        is_set = True
                        break

            if not is_set:
                sum += mapping_values[s[i]]
            i += 1
        return sum



# 🔧 AI 추천 리팩토링 개선버전

아래는 같은 로직을 더 간결하고 효율적으로 표현한 리팩토링 코드입니다.

✅ 개선된 코드

class Solution:
    def romanToInt(self, s: str) -> int:
        sum = 0
        i = 0
        while i < len(s):
            if s[i:i+2] in matching_patterns:
                sum += matching_patterns[s[i:i+2]]
                i += 2
            else:
                sum += mapping_values[s[i]]
                i += 1
        return sum

✨ 개선 포인트
for ... in 반복 없이 s[i:i+2] in dict로 체크 → 더 빠르고 간단
	•	is_set 플래그 제거로 코드가 더 읽기 쉬움
	•	불필요한 딕셔너리 키 반복 제거

결과적으로, 시간복잡도는 여전히 $$O(n)$$ 이지만 평균 성능이 더 나아지고 코드 품질도 향상됩니다.


💡 Tip: 딕셔너리에서 키 존재 여부를 확인할 때는 key in dict를 활용하면 훨씬 효율적인 경우가 많습니다.