13. Roman to Integer题目和答案详解
来源:互联网 发布:k歌之王65首歌名知乎 编辑:程序博客网 时间:2024/05/21 10:13
1 题目简述
Given aroman numeral, convert it to an integer.
Input isguaranteed to be within the range from 1 to 3999.
给定一个罗马数字,将其转换为整数。
输入保证在1到3999的范围内。
2 答案详解(1) 规则分析
首先,要知道罗马数字有7个:I(1),V(5),X(10),L(50),C(100),D(500),M(1000)。然后要知道罗马计数的一些规则,先来看这样的例子:阿拉伯数字1~11用罗马数字表示为:
I、II、III、IV、V、VI、VII、VIII、IX、X、XI
以此为例,说明四点一般规则:
1)只有I、X、C可作为余下数字的前缀,例如VM、LC则为非法。
2)对于I、X、C(1开头的数字,M除外)来说,单次使用量最多不能4个,这是因为IIII是非法的,IV才是正确合法的,还有XXXX是非法的,XL才是正确合法的。
3)对于V、L、D(5开头的数字)来说,单次使用量最多为1个,这是因为VV不能表示10,而X才表示10。
4)此外,还有一些非法数字的情况,例如:XIIX,它符合前3点规则,将其分开为XI和IX,即为11和9,相加得20,但XX才表示20,故XIIX是非法的。同理,DCCCD也是非法的。ps:一个阿拉伯数字只有一种罗马数字表示法。
注意:罗马数字表示法还有一种规则是在数字上方加上横线,表示其1000倍的数,但对于本次题目,上述四项规则已经足以解决。
(2) 解决思想
根据所述规则,由于采用C++来编写程序,而C++相对于C语言特性中重要的一点是面向对象编程(OOP),故本次设计采用类的方法实现,该类表明所存储的数据类型为vector<char>的容器。设计总体分两步进行:
1)初步判断输入的罗马数字是否合法。首先,若输入的字母中含有7个罗马数字之外的数字,则为非法;然后,若是违反了前三项规则,则为非法。依次将合法的数字放入容器中。在初步判断正确的情况下,仍然无法避免会违反第四项规则。对于是否符合第四项规则的合法性,则留给将初步合法的数字转化为阿拉伯数字时判断。
2)从头开始遍历容器,从高位到低位,依次将每一项加入到结果中。对于有前缀的项,有且只有一个前缀数字(例如IV、IX),故I、X、C若是遇到比其大的数字则求其组合代表的阿拉伯数字值(例如求IV为4,IX为9);对于有后缀的项则不用将其组合,因为VIII为5+1+1+1的值;对于第四项规则的处理,可以看到加入到结果中的项是从高位加到低位的,所以若在累加的过程中,遇到前一个加入的项小于后一个加入的项时,则为非法(例如XIIX:9+1+10,1比10小,所以该数字非法),这是因为从高位到低位的项只可能越来越小;最后,对于保证罗马数字的值在1~3999范围,则由最后的结果判断。
(3) 设计程序
所设计的程序采用类模板,虽然本次模板设计没有体现其延伸性和代码重用性,但也是出于此目的所养成的习惯。程序如下:
#include <iostream>#include <vector>#include <algorithm>using std::cin;using std::cerr;using std::cout;using std::endl;using std::vector;void display(char& c){ cout << c;}template<class T>class RomanToInteger{private: vector<T> romans_;public: RomanToInteger(const vector<T>& romans = vector<T>(0)):romans_(romans) {} int result();private: void judge(); void exit_() { cerr << "Wrong Input" << endl; exit(EXIT_FAILURE); } void out_range() const { cerr << "Out of Range" << endl; exit(EXIT_FAILURE); }};template<class T>void RomanToInteger<T>::judge(){ typename vector<T>::iterator it; int count; int left; for(it = romans_.begin(); it != romans_.end(); it++) { left = distance(it,romans_.end()); if(left == 0) { exit_(); } else if(*it == 'C' or *it == 'X' or *it == 'I') { if(left > 3 and *it == *(it + 1) and *it == *(it + 2) and *it == *(it + 3)) { exit_(); } else if(left > 1 and *it == 'I' and (*(it + 1) == 'L' or *(it + 1) == 'C' or *(it + 1) == 'D' or *(it + 1) == 'M')) { exit_(); } else if(left > 1 and *it == 'X' and (*(it + 1) == 'D' or *(it + 1) == 'M')) { exit_(); } } else if(*it == 'D' or *it == 'L' or *it == 'V') { if(left > 1 and *it == *(it + 1)) { exit_(); } else if(left > 1 and *it == 'V' and (*(it + 1) == 'X' or *(it + 1) == 'L' or *(it + 1) == 'C' or *(it + 1) == 'D' or *(it + 1) == 'M')) { exit_(); } else if(left > 1 and *it == 'L' and (*(it + 1) == 'C' or *(it + 1) == 'D' or *(it + 1) == 'M')) { exit_(); } else if(left > 1 and *it == 'D'and *(it + 1) == 'M') { exit_(); } } } cout << "The Number is:"; for_each(romans_.begin(),romans_.end(),display); cout << endl; return;}template<class T>int RomanToInteger<T>::result(){ judge(); int res(0); int add(0); int add_before(0); typename vector<T>::iterator it; for(it = romans_.begin(); it != romans_.end(); it++) { if(*it == 'I') { if(*(it + 1) == 'X') { add = 9; it++; } else if(*(it + 1) == 'V') { add = 4; it++; } else { add = 1; } } else if(*it == 'V') { add = 5; } else if(*it == 'X') { if(*(it + 1) == 'C') { add = 90; it++; } else if(*(it + 1) == 'L') { add = 40; it++; } else { add = 10; } } else if(*it == 'L') { add = 50; } else if(*it == 'C') { if(*(it + 1) == 'M') { add = 900; it++; } else if(*(it + 1) == 'M') { add = 400; it++; } else { add = 100; } } else if(*it == 'D') { add = 500; } else if(*it == 'M') { add = 1000; } if(!add_before) { add_before = add; } else if(add_before < add) { exit_(); } else { add_before = add; } res += add; if(res > 3999) { out_range(); } } if(res == 0) { out_range(); } return res;}int main(){ vector<char> vec; char ch; int res; cout << "Please Iuput Number of Roman:"; while((ch = cin.get()) != '\n') { if(ch != 'M'and ch != 'D'and ch != 'C'and ch != 'L'and ch != 'X'and ch != 'V' and ch != 'I') { cerr << "Wrong Input" << endl; exit(EXIT_FAILURE); } else { vec.push_back(ch); } } RomanToInteger<char> rti(vec); res = rti.result(); cout << "Integer Number:" << res << endl;}本次测试了4种不同输入情况的运行结果,运行结果为:
Please Iuput Number of Roman:ASDCF
Wrong Input
Please Iuput Number of Roman:VX
Wrong Input
Please Iuput Number of Roman:XIIX
The Number is:XIIX
Wrong Input
Please Iuput Number of Roman:MDCLXVI
The Number is:MDCLXVI
Integer Number:1666
- 13. Roman to Integer题目和答案详解
- Easy-题目13:13. Roman to Integer
- 12. Integer to Roman 和 13. Roman to Integer
- LeetCode 13. Roman to Integer和12. Integer to Roman
- LeetCode题目:Integer to Roman
- LeetCode题目:Roman to Integer
- 7.Reverse Integer题目和答案详解
- 13. Roman to Integer
- 13.Roman to Integer
- 13. Roman to Integer
- 13.Roman to Integer
- 13. Roman to Integer
- 13. Roman to Integer
- 13. Roman to Integer
- 13. Roman to Integer
- 13. Roman to Integer
- 13. Roman to Integer
- 13. Roman to Integer
- 【LeetCode】27.Remove Element(Easy)解题报告
- 【Scikit-Learn 中文文档】半监督学习
- 106张图为证,配置SSLVPN服务
- Action的三种访问方式(八)
- 私有云落地解决方案之openstack高可用(pike版本)-环境配置
- 13. Roman to Integer题目和答案详解
- 深度优先算法(DFS)遍历有向无环图计算最优路径
- 1.0-springboot的java配置方式
- 给键盘按键带上音效
- 中介者模式
- JavaScript学习笔记——对象和数组(下)
- 一步步点亮LED
- 【Scikit-Learn 中文文档】概率校准
- 73. Set Matrix Zeroes