Valid Roman Numeral
正则表达式
思路
首先我们要熟悉罗马数的表达方式。M是1000,D是500,C是100,L是50,X是10,V是5,I是1。验证字符串是否是罗马数,我们先看一下有效的罗马数是什么样的,假设该数字小于5000,从千位到个位依次拆解。
千位的表达方式 M{0,4}
MMMM 4000
MMM 3000
MM 2000
M 1000
百位的表达方式 (CM|CD|D?C{0,3})
CM 900
DCCC 800
DCC 700
DC 600
D 500
CD 400
CCC 300
CC 200
C 100
十位的表达方式 (XC|XL|L?X{0,3})
XC 90
LXXX 80
LXX 70
LX 60
L 50
XL 40
XXX 30
XX 20
X 10
个位的表达方式 (IX|IV|V?I{0,3})
IX 9
VIII 8
VII 7
VI 6
V 5
IV 4
III 3
II 2
I 1
所以我们正则表达式的就是将这四个部分顺序组合在一起就行了。
注意
罗马数字没有0
正则表达式以
^
开头,以$
结尾
代码
public boolean isRoman(){
if(s.matches("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$")) return true;
return false;
}
Roman to Integer
减大加小法
复杂度
时间 O(N) 空间 O(1)
思路
如果我们通过Valid Roman Numeral确定了一个字符串是罗马数字后,我们就可以用一个非常简单的技巧来计算罗马数字的值,而不用考虑那些非法情况。我们知道罗马数字中较小的字母在较大的字母之前意味着较大的字母减去较小的字母,而较小的字母在较大的字母之后意味着较大的字母加上较小的字母。而且这种前面最多只有1个较小字母。所以我们只要在遍历的过程中记住该字母的上一个就行了。如果该字母比上一个小,说明可以直接加上。如果该字母比上一个大,说明正确的值应该是该字母减去上一个字母,而我们之前已经加上了上一个字母,所以我们要减去两倍的上一个字母,然后再加上当前字母。
代码
public class Solution {
public int romanToInt(String s) {
int total = charToInt(s.charAt(0));
for(int i = 1; i < s.length(); i++){
int prev = charToInt(s.charAt(i-1));
int curr = charToInt(s.charAt(i));
if(curr <= prev){
total += curr;
} else {
total = total - 2 * prev + curr;
}
}
return total;
}
public int charToInt(char c) {
int data = 0;
switch (c) {
case 'I':
data = 1;
break;
case 'V':
data = 5;
break;
case 'X':
data = 10;
break;
case 'L':
data = 50;
break;
case 'C':
data = 100;
break;
case 'D':
data = 500;
break;
case 'M':
data = 1000;
break;
}
return data;
}
}
Integer to Roman
贪心法
复杂度
时间 O(N) 空间 O(1)
思路
因为罗马数字都是由最大化的表示,比如10会表示成X而不是VV,所以我们可以从最大可能的表示向小的依次尝试。因为提示1-3999,所有的可能性不多,我们可以直接打表来帮助我们选择表示方法。在一个数量级中有四种可能的表示方法,以1-9为例,1-3是由I表示出来的,4是IV,5是V,6-8是V和若干个I,9是IX。
代码
public class Solution {
public String intToRoman(int num) {
String[] symbol = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
int[] value = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
StringBuilder res = new StringBuilder();
int i = 0;
while(num>0){
if(num>=value[i]){
res.append(symbol[i]);
num -= value[i];
} else {
i++;
}
}
return res.toString();
}
}