Saturday, March 7, 2015

Roman to Integer

Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
提示:罗马数字规则
羅馬數字共有7個,即I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)。按照下述的規則可以表示任意正整數。需要注意的是罗马数字中没有“0”,與進位制無關。一般認為羅馬數字只用來記數,而不作演算。
  • 重複數次:一個羅馬數字重複幾次,就表示這個數的幾倍。
  • 右加左減:
    • 在較大的羅馬數字的右邊記上較小的羅馬數字,表示大數字加小數字。
    • 在較大的羅馬數字的左邊記上較小的羅馬數字,表示大數字减小數字。
    • 左减的数字有限制,仅限于I、X、C。比如45不可以写成VL,只能是XLV
    • 但是,左減時不可跨越一個位數。比如,99不可以用IC(100 - 1)表示,而是用XCIX([100 - 10] + [10 - 1])表示。(等同於阿拉伯數字每位數字分別表示。)
    • 左減數字必須為一位,比如8寫成VIII,而非IIX。
    • 右加數字不可連續超過三位,比如14寫成XIV,而非XIIII。(見下方“數碼限制”一項。)
  • 加線乘千:
    • 在羅馬數字的上方加上一條橫線或者加上下標的Ⅿ,表示將這個數乘以1000,即是原數的1000倍。
    • 同理,如果上方有兩條橫線,即是原數的1000000(1000^{2})倍。
  • 數碼限制:
    • 同一數碼最多只能出現三次,如40不可表示為XXXX,而要表示為XL。
    • 例外:由於IV是古羅馬神話主神朱庇特(即IVPITER,古羅馬字母裡沒有J和U)的首字,因此有時用IIII代替IV。
Solution
I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)
维护一个整数,如果1下一个字符是对应位的5或者10则减对应位的1,否则加之。遇到5或者10就直接加上对应位的5或者10。
如果10下一个字符是对应位的50或者100则减对应位的10,否则加之。遇到50或者100就直接加上对应位的50或者100。
如果100下一个字符是对应位的500或者1000则减对应位的100,否则加之。遇到500或者1000就直接加上对应位的500或者1000。
时间复杂度是O(字符串的长度),空间复杂度是O(1)。
public class Solution {
    public int romanToInt(String s) {
        if(s == null || s.length() == 0)
            return 0;
        
        int res = 0;
        for(int i = 0; i < s.length(); i++) {
            switch(s.charAt(i)) {
                case 'I':
                    if(i < s.length() - 1 && (s.charAt(i + 1) == 'V' || s.charAt(i + 1) == 'X')) {
                        res -= 1;
                    }else {
                        res += 1;
                    }
                    break;
                case 'V':
                    res += 5;
                    break;
                case 'X': 
                    if(i < s.length() - 1 && (s.charAt(i + 1) == 'L' || s.charAt(i + 1) == 'C')) {
                        res -= 10;
                    }else {
                        res += 10;
                    }
                    break;
                case 'L':
                    res += 50;
                    break;
                case 'C':
                    if(i < s.length() - 1 && (s.charAt(i + 1) == 'D' || s.charAt(i + 1) == 'M')) {
                        res -= 100;
                    }else {
                        res += 100;
                    }
                    break;
                case 'D':
                    res += 500;
                    break;
                case 'M':
                    res += 1000;
                    break;
                default:
                    return 0;
            }
        }
        return res;
    }
}
Or
public class Solution {
    public int romanToInt(String s) {
        int i = 0, result = 0;
        int current, later;
        for (i = 0; i < s.length() - 1; i++) {
            current = romanToNumber(s.charAt(i));
            later = romanToNumber(s.charAt(i + 1));
            if (current >= later) {
                result = result + current;
            }else {
                result = result - current;
            }
        }
        result += romanToNumber(s.charAt(s.length()-1));

        return result;
    }
    
    public int romanToNumber(char r) {
        int number = 0;
        switch(r) {
            case 'I':
                number = 1;
                break;
            case 'V':
                number = 5;
                break;
            case 'X':
                number = 10;
                break;
            case 'L':
                number = 50;
                break;
            case 'C':
                number = 100;
                break;
            case 'D':
                number = 500;
                break;
            case 'M':
                number = 1000;
                break;
        }
        return number;
    }
}

No comments:

Post a Comment