Search

Search Form

Results

    No result!

Roman to Integer

December 20, 2024

문제 링크

해결 방법 1

function romanToInt(s: string): number {
  let str = s;
  let res = 0;

  if (str.includes("IV")) {
    res += 4;
    str = str.replace("IV", "");
  } else if (str.includes("V")) {
    res += 5;
    str = str.replace("V", "");
  }

  if (str.includes("IX")) {
    res += 9;
    str = str.replace("IX", "");
  }

  if (str.includes("XL")) {
    res += 40;
    str = str.replace("XL", "");
  } else if (str.includes("L")) {
    res += 50;
    str = str.replace("L", "");
  }

  if (str.includes("XC")) {
    res += 90;
    str = str.replace("XC", "");
  }

  if (str.includes("CD")) {
    res += 400;
    str = str.replace("CD", "");
  } else if (str.includes("D")) {
    res += 500;
    str = str.replace("D", "");
  }

  if (str.includes("CM")) {
    res += 900;
    str = str.replace("CM", "");
  }

  if (str.includes("I")) {
    let arr = [...str.matchAll(/(I)/g)];
    res += arr.length;
  }

  if (str.includes("X")) {
    let arr = [...str.matchAll(/(X)/g)];
    res += arr.length * 10;
  }

  if (str.includes("C")) {
    let arr = [...str.matchAll(/(C)/g)];
    res += arr.length * 100;
  }

  if (str.includes("M")) {
    let arr = [...str.matchAll(/(M)/g)];
    res += arr.length * 1000;
  }

  return res;
}

상당히 코드가 긴 해결 방법이다. 순회 비교 로직도 많이 들어가 있다. 처음에 직관적으로 switch문을 쓰면 더 좋은 방법이 나올 것 같았는데, 일단은 생각나는대로 하다보니 이런 코드가 나왔다. 어찌됐든 테스트 통과도 했고 성능도 그리 나쁘게 나오지는 않았지만, 만족스럽지 못한 코드다.

해결 방법 2

function romanToInt(s: string): number {
  let ans = 0;
  let num = 0;
  let prev = 0;

  for (let i = s.length - 1; i >= 0; --i) {
    /* prettier-ignore */
    switch (s[i]) {
      case 'M': num = 1000; break;
      case 'D': num = 500; break;
      case 'C': num = 100; break;
      case 'L': num = 50; break;
      case 'X': num = 10; break;
      case 'V': num = 5; break;
      case 'I': num = 1; break;
    }

    if (num < prev) {
      ans -= num;
    } else {
      ans += num;
    }
    prev = num;
  }

  return ans;
}

입력 값을 뒤에서부터 순회하면서 최종 반환 값을 누적시켜 나가는 방법이다. 로마숫자 표기법의 특징상 I를 제외한 표기들의 이전 값을 나타낼 때, 자릿수에 따라 자릿수의 최소 표기들(I: 1, X: 10, C: 100. 이 문제의 세계관에서는 M까지 밖에 없음)을 표기 앞에 붙여주는데 이 경우를 처리해주는 로직을 추가해줘야 한다. 그래서 이전 값을 담을 변수를 하나 선언하고 다음 값과 비교해서 다음 값이 더 작으면 다음 값을 누적 값에서 빼주는 로직을 추가했다.

이 결과, 가독성도 좋고 성능도 더 좋은 코드가 되었다.

해결 방법 3 (C++)

class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> m;

        m['I'] = 1;
        m['V'] = 5;
        m['X'] = 10;
        m['L'] = 50;
        m['C'] = 100;
        m['D'] = 500;
        m['M'] = 1000;

        int ans = 0;

        for(int i = 0; i < s.length(); i++){
            if(m[s[i]] < m[s[i+1]]){
                ans -= m[s[i]];
            }
            else{
                ans += m[s[i]];
            }
        }
        return ans;
    }
};

다른 분이 해시맵으로 해결한 방법이다. 좋다.