[LeetCode][12]Integer to Roman解析 int转罗马字符时间复杂度为常数的实现-Java实现

Q:

Given an integer, convert it to a roman numeral.

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

A:

俺是真不知道啥是roman,我去查了一下合着是罗马字体,这题目意思也很简单就是说我要输入一个数字可以保证是1~3999但是你要把这个阿拉伯数字转换成罗马数字。

首先我们要清楚罗马数字怎么表示的,罗马数字表示如下:

数字共有七个,即I(1),V(5),X(10),L(50),C(100),D(500),M(1000)。
并且罗马数字有以下规则:
重复数次:一个罗马数字重复几次,就表示这个数的几倍。 

右加左减:在一个较大的罗马数字的右边记上一个较小的罗马数字,表示大数字加小数字。在一个较大的数字的左边记上一个较小的罗马数字,表示大数字减小数字。但是,左减不能跨越等级。比如,99不可以用IC表示,用XCIX表示。 

加线乘千:在一个罗马数字的上方加上一条横线或者在右下方写M,表示将这个数字乘以1000,即是原数的1000倍。同理,如果上方有两条横线,即是原数的1000000倍。 
上面都是copy来的。
下面我们来仔细研究一下这个题目,无非就是输入的阿拉伯数字a = xI + yV+zX。。。。。。得出x,y,z等的值之后根据规则匹配。我们肯定不会去解这个方程,但是可以肯定的是,他跟阿拉伯数字很像,首先末尾肯定是1~9中间的。加下来就是十位,百位,千位的转化相加了。
我们大概需要以下几种表:
1~9(9个)
10~90(9个)
100~900(9个)
1000~3000(3个)
为什么我们选择对比,因为这样快啊,但是仔细想想,有没有一个公式直接生成呢?
1~3都是1(10、100、1000)叠加的
4~8都是5(50、500)加减1(10、100)得到的
9都是10(100、1000)减掉1(10、100)得到的。
我们也可以用这个规律来运算出来需要转换的数值。
于是我们只需要从尾部开始遍历这个int就好了,具体遍历的方法请看我之前的一篇模仿jdk实现的源码 点击打开链接
具体代码如下:

public class IntegertoRoman {
	public static void main(String[] args){
		int a = 999;
		System.out.println(method(a));
		
	}

	private static String method(int i) {
		// TODO Auto-generated method stub
		int r =0;
		int q = 1;
		int times = 0;
		String roman ="";
		while (true) {
			times ++;
			q = (i * 52429) >>> 19;//去尾1位,2<<(16+3)=524288 52429/524288约为0.1
			r = i - ((q << 3) + (q << 1));//r=i-q*10,截出最后一位
			i=q;
			
			switch(times){
				case 1://个位
					roman = convertRoman(r, "I", "V", "X");
					break;
				case 2://十位
					roman = convertRoman(r, "X", "L", "C")+roman;
					break;
				case 3://百位
					roman = convertRoman(r, "C", "D", "M")+roman;
					break;
				case 4://千位
					roman = convertRoman(r, "M", "null", "null")+roman;
					break;
			}
			if(q==0)break;
		}
		return roman;
	}
	/**
	 * 一位罗马数字转化
	 * @param r 需要转化的罗马数字
	 * @param one 这一位代表1的罗马字母
	 * @param five 这一位代表5的罗马字母
	 * @param ten 这一位代表10的罗马字母
	 * @return
	 */
	public static String convertRoman(int r,String one,String five,String ten){
		String roman ="";
		if(r==0)
			return "";
		else if(0<r&&r<=3){//one
			String s = "";
			for(int k = 0;k<r;k++){
				s+=one;
			}
			roman = roman+s;
		}
		else if(3<r&&r<=8){//five+/-one
			String s = "";
			if(r==4){
				s=one+five;
			}else {
				for(int k = 5;k<r;k++){
					s+=one;
				}
				s= five+s;
			}
			roman = roman+s;
		}else if(r == 9){//ten-one
			roman = one+ten;
		}
		return roman;
	}
perfect~完美解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值