題目描述
羅馬數字包含以下七種字符:I
, V
, X
, L
, C
, D
和M
。
字符數值
I
:1
V
: 5
X
:10
L
:50
C
:100
D
:500
M
:1000
例如,羅馬數字2
寫作II
,即爲兩個並列的I
。12
寫作XII
,即爲X + II
。 27
寫作XXVII
,即爲XX + V + II
.
通常情況下,羅馬數字中小的數字在大的數字的右邊。但也存在特例,例如4
不寫作IIII
, 而是IV
。數字1
在數字5
的左邊,所表示的數等於大數5
減去小數1
得到的數值4
。同樣地,數字9
表示爲IX
。這個特殊的規則只適用於以下六種情況:
I
可以放在V
和X
的左邊,來表示數字4, 9
;X
可以放在L
和C
的左邊,用來表示數字40, 90
;C
可以放在D
和M
的左邊,來表示數字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 大多數情況下的累加,觀察字符串,我們採用從右至左的角度,當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。