算法修煉之路—【字符串】Leetcode 13 羅馬數字轉整數

題目描述

羅馬數字包含以下七種字符:I, V, X, L, C, DM

字符數值
I :1
V: 5
X:10
L:50
C:100
D :500
M:1000

例如,羅馬數字2寫作II,即爲兩個並列的I12寫作XII,即爲X + II27寫作XXVII,即爲XX + V + II.

通常情況下,羅馬數字中小的數字在大的數字的右邊。但也存在特例,例如4不寫作IIII, 而是IV。數字1在數字5的左邊,所表示的數等於大數5減去小數1得到的數值4。同樣地,數字9表示爲IX。這個特殊的規則只適用於以下六種情況:

  • I可以放在VX的左邊,來表示數字 4, 9
  • X可以放在LC的左邊,用來表示數字40, 90
  • C可以放在DM的左邊,來表示數字400, 900

給定一個羅馬數字,將其轉換成整數。確保在1-3999的範圍內。

示例1:

輸入: s = “III”
輸出: 3

示例2:

輸入: s = “IV”
輸出: 4

示例3:

輸入: s = “IX”
輸出: 9

示例4:

輸入: s = “LVIII”
輸出: 58
解釋: L = 50, V = 5, III = 3.

示例5:

輸入: s = “MCMXCIV”
輸出: 1994
解釋: M = 1000, CM = 900, XC = 90, IV = 4.

思路分析

這道題難度爲簡單, 通過題意我們可以先將其看作簡單的轉換,接着是一個數值累加的過程,只不過這裏存在着一些特殊情況爲減去值,那麼我們將規律儘量統一化:

  1. 大多數情況下,爲累加
  2. 特殊情況下,爲減去當前值

對於情況1 大多數情況下的累加,觀察字符串,我們採用從右至左的角度,當val(rightNum) >= val(curr)時,此時爲加法;對於情況2 特殊情況下的減值,當val(currLeft) < val(curr)時,此時爲減法。

通過以上簡單分析我們可知,我們首先需要一個轉換的標準,這裏我們借用HashMap<Character, Integer>來存放題幹中羅馬數字字符與數字的轉換原則;之後我們還需要存在一個記憶變量rightNum,但是僅需存放最新的右邊值即可,即rightNum是隨着遍歷動態刷新的。我們直接給上代碼:

解題代碼

    public static int solution(String s){
        if(s == null || s == "") return 0;
        
        // HashMap to storage rules exchanged.
        Map<Character, Integer> map = new HashMap<>();
        map.put('I', 1);
        map.put('V', 5);
        map.put('X', 10);
        map.put('L', 50);
        map.put('C', 100);
        map.put('D', 500);
        map.put('M', 1000);       
        
        
        int len = s.length();
        int rightNum = map.get(s.charAt(len - 1));
        int res = rightNum;
        
        for(int i = len-2;i>=0;i--){
            int cur = map.get(s.charAt(i));
            if(cur < rightNum)
                res -= cur;
            else if(cur >= rightNum)
                res += cur;
            rightNum = cur;
        }
        return res;
    }

複雜度分析

時間複雜度: 我們對字符串進行了一次遍歷,故時間複雜度爲O(N);
空間複雜度: 我們雖然對轉換規則進行了HashMap存儲,但是其不隨N變化,所以空間複雜度爲O(1).

Github源碼

完整可運行文件請訪問GitHub

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章