LeetCode 12_Integer to Roman

这几天没别的事情,抓紧时间多写几道。今天给大家带来的是leetcode第12题,题目要求也很简单直接,就是把阿拉伯数字。其实呢,阿拉伯数字是印度人发明的,阿拉伯人只是二道贩子,有兴趣的朋友可以去查一下相关资料。而罗马数字大家肯定也都听过,不过因为其使用上不如阿拉伯数字方便,所以平常生活中并不会用到。当然这里不是来说这些事儿的,我们还是说题目吧

Given an integer, convert it to a roman numeral.

Input is guaranteed to be within the range from 1 to 3999.

这个就没啥可说的了,之所以要规定范围,就是因为罗马数字的增长规律比较难掌握,再往上可能就会出现更多的情况,这再一次说明了罗马数字使用不便,同时也启示我们发明创造要以简单直观为目标,很复杂的东西往往推广和使用都会遇到很多困难,,,好像又扯远了

罗马数字大家都听过也见过,不过真的要你说出个一二三四五来恐怕也没几个人能做到,说白了,也就是大一点的数怎么表达很多人都不知道。这就不用说了,百度一下吧。

其实这道题就是考察你对罗马数字表示方法的理解的,这个东西不同人有不同见解,我就不多说了,直接说说我的思路吧:首先,转化规律是比较复杂的,就每一位来说,都需要至少三种判断才能决定最终表达形式。就比如说个位吧,1到3是一种情况,4是一种情况,5到8是一种情况,9是一种情况,这里说的一种情况我想大家都理解是啥意思,当然通过一些特殊手段可能会合并几种情况,但目测是很难合并到少于三种的,总之,靠转化规律编程不是好的方法。其次,通过简单的总结可以看出阿拉伯数字的每一位(含权重)和罗马数字有对应关系,且输入有限制,所以可以考虑利用对照表来“蛮力解决”。最后,通过进一步分析(其实就是找规律),发现虽然每一位的表示字母不同,但字母的变化规律相同,即1到9和10到90只是用的字母不同了,其形式是一样的,这样启示我们可以找到一个比较统一的表达方法。

在这里,我用了对照表的蛮力法和子函数的规律法分别编码,代码如下:

对照表蛮力法:

class Solution {
public:
    string intToRoman(int num) {
		vector<string> tho;tho.resize(3);
		tho[0]="M";tho[1]="MM";tho[2]="MMM";
		vector<string> hun;hun.resize(9);
		hun[0]="C";hun[1]="CC";hun[2]="CCC";
		hun[3]="CD";hun[4]="D";hun[5]="DC";
		hun[6]="DCC";hun[7]="DCCC";hun[8]="CM";
		vector<string> ten;ten.resize(9);
		ten[0]="X";ten[1]="XX";ten[2]="XXX";
		ten[3]="XL";ten[4]="L";ten[5]="LX";
		ten[6]="LXX";ten[7]="LXXX";ten[8]="XC";
		vector<string> bit;bit.resize(9);
		bit[0]="I";bit[1]="II";bit[2]="III";
		bit[3]="IV";bit[4]="V";bit[5]="VI";
		bit[6]="VII";bit[7]="VIII";bit[8]="IX";

		string result;
		if(num/1000>0)
		{
			result += tho[num/1000-1];
			num %= 1000;
		}
		if(num/100>0)
		{
			result += hun[num/100-1];
			num %= 100;
		}
		if(num/10>0)
		{
			result += ten[num/10-1];
			num %= 10;
		}
		if(num>0)
		{
			result += bit[num-1];
		}

        return result;
    }
};
这个代码并没有什么好说的,只是分析到了阿拉伯数字和罗马数字之间有简单的对应关系,通过建立这种对应关系建立对照表(也可以称为翻译表),最后通过查表来翻译数字。这种方法的缺点在于每一次翻译都要将表构建一次,由于表的内容相对于转化过程比较多,所以程序执行的很多时间都浪费在了建表上,可以说是“白白浪费了”。

下面是子函数的规律法

string convert(const int &n,const int& index)
{
	string table="IVXLCDM";
	string result;
	switch(n)
	{
	case 0: break;
	case 1: result += table[index];break;
	case 2: result += table[index]; 
		result += table[index];break;
	case 3: result += table[index]; 
		result += table[index];
	<span style="white-space:pre">	</span>result += table[index];break;
	case 4: result += table[index]; 
		result += table[index+1];break;
	case 5: result += table[index+1];break;
	case 6: result += table[index+1]; 
		result += table[index];break;
	case 7: result += table[index+1]; 
		result += table[index]; 
		result += table[index];break;
	case 8: result += table[index+1]; 
		result += table[index]; 
		result += table[index]; 
		result += table[index];break;
	case 9: result += table[index]; 
		result += table[index+2];break;
	}
	return result;
}

class Solution {
public:
    string intToRoman(int num) {
		string result;
		if(num/1000>0)
		{
			result += convert(num/1000,6);
			num %= 1000;
		}
		if(num/100>0)
		{
			result += convert(num/100,4);
			num %= 100;
		}
		if(num/10>0)
		{
			result += convert(num/10,2);
			num %= 10;
		}
		if(num>0)
		{
			result += convert(num,0);
		}
		return result;
	}
		
};
这个代码和前面的相比就是多分析了一步,注意到了个十百千位的规律是相同的(即比如说7和70以及700的表达形式是一样的),不过看起来并没有简化多少,而程序的运行时间每次都不固定,有时候是40ms有时候是32ms(上面那个是36ms)所以说下面这个虽然分析多了一步,看起来“更像”是一种算法了,但具体改进的怎么样还是不好说的。

32m的成绩算是比较不错了,所以也就没有再进一步思考,还是那句话,这种情况再改进也不是算法的考虑范围了,跟语言的一些实现有比较大的关系,而且正如前面所说,评价体系并不是十分稳定。

接下来就是看大神的代码了,有没有新的算法出现呢?我没有看完,但基本也可以排除了,大家用的都是类似的构建翻译表的方法,只是有些代码更简练一些,由于与算法无关,这里就不给大家发了。

今天写的比较少,主要是这题并没有什么理解上的难度也没有隐藏很深的信息,这样也就没有地方可以让算法来发挥作用了。要说考察点,那就是考察的翻译表或者翻译函数的建立吧。

不多说了,抓紧时间再来一道。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值