Coding Challenges/LeetCode

[Java] 13. Roman to Integer

기록해연 2025. 2. 4. 10:11

난이도: EASY


문제

더보기

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.

Constraints:
1 <= s.length <= 15
s contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M').
It is guaranteed that s is a valid roman numeral in the range [1, 3999].


 

중간 오류1 (비교연산자 실수)

class Solution {
    public int romanToInt(String s) {
        int num = 0;
        
        for(int i = s.length() - 1; i >= 0; i--) {
            System.out.println("i > " + i);
            System.out.println("s.charAt(i) > " + s.charAt(i));
            // 맨 뒤부터 매칭
            if("I".equals(s.charAt(i))) {
                num += 1;
            } else if("V".equals(s.charAt(i))) {
                num += 5;
            } else if("X".equals(s.charAt(i))) {
                num += 10;
            } else if("L".equals(s.charAt(i))) {
                num += 50;
            } else if("C".equals(s.charAt(i))) {
                num += 100;
            } else if("D".equals(s.charAt(i))) {
                num += 500;
            } else if("M".equals(s.charAt(i))) {
                num += 1000;
            } 

            System.out.println("num? " + num);
        }
        return num;
    }   
}

//------------------------- 수정된 코드 ------------------------------------
class Solution {
    public int romanToInt(String s) {
        int num = 0;
        
        for(int i = s.length() - 1; i >= 0; i--) {            
            System.out.println("s.charAt(i) > " + s.charAt(i));
            
            // 맨 뒤부터 매칭
           if (s.charAt(i) == 'I') {
                num += 1;
            } else if (s.charAt(i) == 'V') {
                num += 5;
            } else if (s.charAt(i) == 'X') {
                num += 10;
            } else if (s.charAt(i) == 'L') {
                num += 50;
            } else if (s.charAt(i) == 'C') {
                num += 100;
            } else if (s.charAt(i) == 'D') {
                num += 500;
            } else if (s.charAt(i) == 'M') {
                num += 1000;
            }

            System.out.println("num? " + num);
        }
        return num;
    }
    
}

우선 다른조건 무시하고 단순 출력해보고 있었는데, 모든 input에서 0인 것 임.

=> 멍청하게 char랑 String을 equals로 비교하고 있어서 조건문이 안걸림 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 그래서 아래로 바꿔줌.

 

중간 오류1 (연산 범위 실수)

class Solution {
    public int romanToInt(String s) {
        int num = 0;
        
        for(int i = s.length() - 1; i >= 0; i--) {            
            System.out.println("s.charAt(i) > " + s.charAt(i));

            // 맨 뒤부터 매칭
           if (s.charAt(i) == 'I') {
                num += 1;
            } else if (s.charAt(i) == 'V') {
                num += (s.charAt(i - 1) == 'I') ? 4 : 5;               
            } else if (s.charAt(i) == 'X') {
                num += (s.charAt(i - 1) == 'I') ? 9 : 10;
            } else if (s.charAt(i) == 'L') {
                num += (s.charAt(i - 1) == 'X') ? 40 : 50;                                
            } else if (s.charAt(i) == 'C') {
                num += (s.charAt(i - 1) == 'X') ? 90 : 100;
            } else if (s.charAt(i) == 'D') {
                num += (s.charAt(i - 1) == 'C') ? 400 : 500;
            } else if (s.charAt(i) == 'M') {
                num += (s.charAt(i - 1) == 'C') ? 900 : 1000;
            }

            System.out.println("num? " + num);
        }
        return num;
    }
    
}

//-------------------------- 수정한 소스 --------------------------------

class Solution {
    public int romanToInt(String s) {
        int num = 0;
        
        for(int i = s.length() - 1; i >= 0; i--) {            
            System.out.println("s.charAt(i) > " + s.charAt(i));

            // 맨 뒤부터 매칭
           if (s.charAt(i) == 'I') {
                num += 1;
            } else if (s.charAt(i) == 'V') {
                num += (i - 1 >= 0 && s.charAt(i - 1) == 'I') ? 4 : 5;
            } else if (s.charAt(i) == 'X') {
                num += (i - 1 >= 0 && s.charAt(i - 1) == 'I') ? 9 : 10;
            } else if (s.charAt(i) == 'L') {
                num += (i - 1 >= 0 && s.charAt(i - 1) == 'X') ? 40 : 50;
            } else if (s.charAt(i) == 'C') {
                num += (i - 1 >= 0 && s.charAt(i - 1) == 'X') ? 90 : 100;
            } else if (s.charAt(i) == 'D') {
                num += (i - 1 >= 0 && s.charAt(i - 1) == 'C') ? 400 : 500;
            } else if (s.charAt(i) == 'M') {
                num += (i - 1 >= 0 && s.charAt(i - 1) == 'C') ? 900 : 1000;
            }

            System.out.println("num? " + num);
        }
        return num;
    }
    
}

i-1이 0보다 작을 때(맨 앞의 로마자일때) StringIndexOutOfBoundsException 이 나는 문제 해결


 

나의 최종 제출 답안:

class Solution {
    public int romanToInt(String s) {
        int num = 0;
        
        for(int i = s.length() - 1; i >= 0; i--) {            
            System.out.println("s.charAt(i) > " + s.charAt(i));

            // 맨 뒤부터 매칭
           if (s.charAt(i) == 'I') {
                num += 1;
            } else if (s.charAt(i) == 'V') {
                if (i - 1 >= 0 && s.charAt(i - 1) == 'I') {
                    num += 4;
                    // 다음 문자 건너뛰기
                    i--; 
                } else {
                    num += 5;
                }
            } else if (s.charAt(i) == 'X') {
                if (i - 1 >= 0 && s.charAt(i - 1) == 'I') {
                    num += 9;
                    i--; 
                } else {
                    num += 10;
                }
            } else if (s.charAt(i) == 'L') {
                if (i - 1 >= 0 && s.charAt(i - 1) == 'X') {
                    num += 40;
                    i--; 
                } else {
                    num += 50;
                }
            } else if (s.charAt(i) == 'C') {
                if (i - 1 >= 0 && s.charAt(i - 1) == 'X') {
                    num += 90;
                    i--; 
                } else {
                    num += 100;
                }
            } else if (s.charAt(i) == 'D') {
                if (i - 1 >= 0 && s.charAt(i - 1) == 'C') {
                    num += 400;
                    i--; 
                } else {
                    num += 500;
                }
            } else if (s.charAt(i) == 'M') {
                if (i - 1 >= 0 && s.charAt(i - 1) == 'C') {
                    num += 900;
                    i--; 
                } else {
                    num += 1000;
                }
            }

            System.out.println("num? " + num);
        }
        return num;
    }
    
}

 

근데 이거 뭔가 Map으로 풀고싶었는데, 생각하기싫어서 단순무식한 방법으로 풀음. 결국 챗지선생에게 맡겼다.

 

 

chatGPT에게 더 간단하고 효율적이게 수정해달라고 요청한 답안:

import java.util.Map;

class Solution {
    public int romanToInt(String s) {
        int num = 0;
        
        // 로마 숫자 맵핑
        Map<Character, Integer> romanMap = Map.of(
            'I', 1, 'V', 5, 'X', 10, 'L', 50, 
            'C', 100, 'D', 500, 'M', 1000
        );

        for (int i = s.length() - 1; i >= 0; i--) {
            char current = s.charAt(i);
            int value = romanMap.get(current);

            if (i > 0) { // 이전 문자가 존재할 경우
                char prev = s.charAt(i - 1);
                int prevValue = romanMap.get(prev);

                if (prevValue < value) { // 앞 문자가 작으면 조합된 숫자
                    num += value - prevValue;
                    i--; // 다음 문자 건너뛰기
                    continue;
                }
            }

            num += value;
        }
        return num;
    }
}

 

 

정확한 이해를 위해 다시 챗지방법으로 풀어봄. 

import java.util.Map;

class Solution {
    public int romanToInt(String s) {
        int num = 0;        
        HashMap<Character, Integer> hm = new HashMap<>(Map.of(
            'I', 1,
            'V', 5,
            'X', 10,
            'L', 50,
            'C', 100,
            'D', 500,
            'M', 1000
        ));

        for(int i = s.length() - 1; i >= 0; i--) {            
            char current = s.charAt(i); 
            int val = hm.get(current); // 현재 문자의 값 가져오기

            // 이전 문자 있는 경우
            if(i > 0) {
                char prev = s.charAt(i-1);
                int prevVal = hm.get(prev); // 이전 문자의 값 가져오기
            
                // 앞 문자가 작은 경우 조합수 
                // (작은 숫자가 큰 숫자 앞에 오면, 큰 숫자에서 작은 숫자를 뺀 값으로 해석)
                if(prevVal < val) {
                    num += val - prevVal;
                    i--;
                    // num += val; 안하고 바로 다음 루프 실행
                    continue; 
                }
            }
            num += val;
        }

        return num;
    }
    
}

Map사용시 8~9ms인데 내가 푼건 3ms라 역시 단순한게 짱이군 생각함.....

'Coding Challenges > LeetCode' 카테고리의 다른 글

[SQL50] 1757. Recyclable and Low Fat Products  (0) 2025.02.06
[Java] 20. Valid Parentheses  (0) 2025.02.06
[Java] 14. Longest Common Prefix  (2) 2025.02.05
[Java] 9. Palindrome Number  (1) 2025.02.03
[Java] 1. Two sum  (3) 2025.02.03