leetcode-Integer to Roman
leetcode--Integer to Roman
因为连续的数字重复不得超过三次,所以当大于三次的时候就有特殊的形式。我们不用列出所有30中组合,只要其中特殊的形式(13种),其他的各种形式可由这13种组合得到。将给定整形数最大的对应的罗马字符输出,并减去此罗马字符对应的整形数。这样一直判断,直到给定整形数的个位数也都输出完。代码如下:
第一种方法虽然简单直接,但是空间复杂度大,并且在leetcode中运行时间长为96ms。第二种方法降低了空间复杂度,运行时间为54ms。第三种方法在方法二的思想上进一步减小了空间复杂度,leetcode中运行时间为51ms.

题目描述:
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
题目解析:
将一个整形数的罗马形式表示出来。罗马数字和整形数转换规则参考http://blog.****.net/sinat_24520925/article/details/44560375。
罗马数字是最古老的数字表示方式,比阿拉伯数组早2000多年,起源于罗马
罗马数字有如下符号:
计数规则: 相同的数字连写,所表示的数等于这些数字相加得到的数,例如:III = 3小的数字在大的数字右边,所表示的数等于这些数字相加得到的数,例如:VIII = 8小的数字,限于(I、X和C)在大的数字左边,所表示的数等于大数减去小数所得的数,例如:IV = 4正常使用时,连续的数字重复不得超过三次,在一个数的上面画横线,表示这个数扩大1000倍(本题只考虑3999以内的数,所以用不到这条规则)
其次,罗马数字转阿拉伯数字规则(仅限于3999以内):
罗马数字有如下符号:
基本字符 | I | V | X | L | C | D | M |
对应阿拉伯数字 | 1 | 5 | 10 | 50 | 100 | 500 | 1000 |
其次,罗马数字转阿拉伯数字规则(仅限于3999以内):
下面给出三种算法。
方法一、
首先给出数字对应的罗马字符形式。根据计数规则,我们可以给出30个数字对应的字符串,分别为9(1~9)、9(10~90)、9(100~900)、3(1000~3000)之后将给定的整形数n由高位向低位依次输出其对应的罗马字符。具体代码如下:
string intToRoman(int num) { string M[]={"","M","MM","MMM"}; string C[]={"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"}; string X[]={"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"}; string I[]={"","I","II","III","IV","V","VI","VII","VIII","IX"}; return M[num/1000]+C[(num%1000)/100]+X[(num%100)/10]+I[(num%10)]; }
方法二
string intToRoman2(int num) { if (num>=1000) return "M"+intToRoman(num-1000); if (num>=900) return "CM"+intToRoman(num-900); if (num>=500) return "D"+intToRoman(num-500); if (num>=400) return "CD"+intToRoman(num-400); if (num>=100) return "C"+intToRoman(num-100); if (num>=90) return "XC"+intToRoman(num-90); if (num>=50) return "L"+intToRoman(num-50); if (num>=40) return "XL"+intToRoman(num-40); if (num>=10) return "X"+intToRoman(num-10); if (num>=9) return "IX"+intToRoman(num-9); if (num>=5) return "V"+intToRoman(num-5); if (num>=4) return "IV"+intToRoman(num-4); if (num>=1) return "I"+intToRoman(num-1); return ""; }
方法三
思想同方法二,不过将13个罗马字符和其对应的整形对应存储在数组中,代码如下;
string intToRoman(int num) { for (int i=12;i>=0;i--) { if (inte[i]<=num) { return roman[i]+intToRoman(num-inte[i]); } } return ""; } private: int inte[13]={1,4,5,9,10,40,50,90,100,400,500,900,1000}; string roman[13]={"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};
第一种方法虽然简单直接,但是空间复杂度大,并且在leetcode中运行时间长为96ms。第二种方法降低了空间复杂度,运行时间为54ms。第三种方法在方法二的思想上进一步减小了空间复杂度,leetcode中运行时间为51ms.
完整代码如下,其中我们使用http://blog.****.net/sinat_24520925/article/details/44560375中的roman to integer函数来判断roman
to integer三种算法的正确性。
#include <iostream> #include <string> #include <vector> using namespace std; int romanToInt(string s) ; string intToRoman(int num) ; string intToRoman1(int num); string intToRoman2(int num); void main() { int n=2549; cout<<n<<endl; string res=intToRoman(n) ; cout<<res<<endl; cout<<romanToInt(res)<<endl; string res1=intToRoman1(n) ; cout<<res1<<endl; cout<<romanToInt(res1)<<endl; string res2=intToRoman2(n) ; cout<<res2<<endl; cout<<romanToInt(res2); } string intToRoman(int num) { string M[]={"","M","MM","MMM"}; string C[]={"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"}; string X[]={"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"}; string I[]={"","I","II","III","IV","V","VI","VII","VIII","IX"}; return M[num/1000]+C[(num%1000)/100]+X[(num%100)/10]+I[(num%10)]; } int inte[13]={1,4,5,9,10,40,50,90,100,400,500,900,1000}; string roman[13]={"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"}; string intToRoman1(int num) { for (int i=12;i>=0;i--) { if (inte[i]<=num) { return roman[i]+intToRoman(num-inte[i]); } } return ""; } string intToRoman2(int num) { if (num>=1000) return "M"+intToRoman(num-1000); if (num>=900) return "CM"+intToRoman(num-900); if (num>=500) return "D"+intToRoman(num-500); if (num>=400) return "CD"+intToRoman(num-400); if (num>=100) return "C"+intToRoman(num-100); if (num>=90) return "XC"+intToRoman(num-90); if (num>=50) return "L"+intToRoman(num-50); if (num>=40) return "XL"+intToRoman(num-40); if (num>=10) return "X"+intToRoman(num-10); if (num>=9) return "IX"+intToRoman(num-9); if (num>=5) return "V"+intToRoman(num-5); if (num>=4) return "IV"+intToRoman(num-4); if (num>=1) return "I"+intToRoman(num-1); return ""; } int romanToInt(string s) { /*roman['I']=1; roman['V']=5; roman['X']=10; roman['L']=50; roman['C']=100; roman['D']=500; roman['M']=1000; */ char *p=new char[s.size()]; strcpy(p,s.c_str());//将string型转为char型数组 vector<int> array; array.resize(s.size()); int n=0; for (int i=0;i<s.size();i++) { switch (p[i]) { case 'I':array[i]=1;break; case 'V':array[i]=5;break; case 'X':array[i]=10;break; case 'L':array[i]=50;break; case 'C':array[i]=100;break; case 'D':array[i]=500;break; case 'M':array[i]=1000;break; default:cout<<"error\n"; } if (i==0) { n+=array[i]; } else { if (array[i]<=array[i-1]) { n+=array[i]; } else { n+=array[i]-2*array[i-1]; } } } return n; }