Roman to Integer
题目要求:
给定一个罗马数字,将其转换为整数。
输入确保在1到3999范围内。
罗马数字定义:
- 罗马数字共有七个,即I(1),V(5),X(10),L(50),C(100),D(500),M(1000)。按照下面的规则可以表示任意正整数。
- 重复数次:一个罗马数字重复几次,就表示这个数的几倍。
- 右加左减:
在一个较大的罗马数字的右边记上一个较小的罗马数字,表示大数字加小数字。
在一个较大的数字的左边记上一个较小的罗马数字,表示大数字减小数字。
但是,左减不能跨越等级。比如,99不可以用IC表示,用XCIX表示。 - 加线乘千:在一个罗马数字的上方加上一条横线或者在右下方写M,表示将这个数字乘以1000,即是原数的1000倍。同理,如果上方有两条横线,即是原数的倍。
- 单位限制:同样单位只能出现3次,如40不能表示为XXXX,而要表示为XL。
组合规则:
(1) 基本数字 Ⅰ、X 、C 中的任何一个,自身连用构成数目,或者放在大数的右边连用构成数目,都不能超过三个;放在大数的左边只能用一个。
(2) 不能把基本数字 V 、L 、D 中的任何一个作为小数放在大数的左边采用相减的方法构成数目;放在大数的右边采用相加的方式构成数目,只能使用一个。
(3) V 和 X 左边的小数字只能用 Ⅰ。
(4)L 和 C 左边的小数字只能用 ×。
(5)D 和 M 左 边的小数字只能用 C 。
还有一点需要格外注意:
MCM是1900
MCMXCVI是1996
按照逻辑 遍历到C 的处理,MC先M+C,但是遍历到第二个M的时候,顺序是CM,这个时候要减去这个C以及之前多加的C,也就是减去两个C。
例子:XCIX 是 99 遍历到第二个X时,+10-2*1
代码实现:
//转化罗马数字为整数 #include <iostream> #include<string> #include<stdlib.h> using namespace std; class Solution {
public: //116ms int romanToInt(string s) {
//从左往右 if (s.length() <= 1) return charToInt(s[0]); int res = charToInt(s[0]); for (int i = 1; i<s.length(); i++){
if (charToInt(s[i])>charToInt(s[i - 1])) res = res + charToInt(s[i]) - 2 * charToInt(s[i - 1]); else res += charToInt(s[i]); } return res; } int charToInt(char s){
switch (s) {
case 'I': return 1; case 'V': return 5; case 'X': return 10; case 'L': return 50; case 'C': return 100; case 'D': return 500; case 'M': return 1000; default: return 0; } } }; int main() {
Solution a; string s; cin >> s; cout << a.romanToInt(s) << endl; system("pause"); return 0; }
试着将罗马数字从右往左进行转化
//89ms int romanToInt1(string s) {
//从右往左 if(s.length()<=1) return charToInt(s[0]); int res = 0; char maxChar = 'I'; for(int i=s.size()-1; i>=0; --i){
if(charToInt(s[i])>=charToInt(maxChar)){
maxChar = s[i]; res += charToInt(s[i]); } else res -= charToInt(s[i]); } return res; }
效率更高的方法:
- 当利用了罗马数字两个数字前后顺序的关系,也就是说如果是I在V前面,也就是IV,它代表4,反之代表6。再搭配C++的unordered_map,可以巧妙的通过数组来进行判断而达到对ret或加或减的目的。
//52ms #include <unordered_map> int romanToInt2(string s){
unordered_map<char, int> map = {
{
'I', 1}, {
'V', 5}, {
'X', 10}, {
'L', 50}, {
'C', 100}, {
'D', 500}, {
'M', 1000}}; int res = 0; for (int i = 0; i < s.size(); ++i) {
if ((i < s.size()-1) && (map[s[i]] < map[s[i+1]])) {
res -= map[s[i]]; } else {
res += map[s[i]]; } } return res; }
Integer to Roman
整数转化为罗马数字
代码实现:
#include <iostream> using namespace std; class Solution {
public: string intToRoman(int num) {
//整数转化为罗马数字 string M[] = {
"", "M", "MM", "MMM"}; //1000 - 3000 string C[] = {
"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; //100 - 900 string X[] = {
"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; //10 - 90 string I[] = {
"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; //0 - 9 return M[num/1000] + C[(num/100)%10] + X[(num/10)%10] + I[num%10]; } }; int main(){
Solution a; int num; cin >> num; cout << a.intToRoman(num) << endl; return 0; }