罗马数字与整数互相转换

最近开始尝试在leecode网站上做一些较简单的算法题

目前底子比较薄,暂时还只能做一些简单的题目,这里记录了一个比较经典的题目:
罗马数字与整数的互相转换:

  • 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

一开始看到题目百思不得其解,完全无从下手,后来还是看了评论区的答案才有了思路:
首先建立一个HashMap来映射符号和值,然后对字符串从左到右来,如果当前字符代表的值不小于其右边,就加上该值;否则就减去该值。以此类推到最左边的数,最终得到的结果即是答案
主要观察罗马数字的规律:4,9,40,90,400,900这几个数都要先累加再减
如果前一个字符是"I",后一个数字是"V",“X"那么累加的时候先累加在减二,如果前一个数字是"X”,后一个数字是"L"或者"C",就减20,如果前一个数字是"C",后一个数字是"D"或者"M",就减200;

  • 代码如下
public static int romanToInt(String s) {
		 Map<Character, Integer> map = new HashMap<>();
		 map.put('I', 1);
		 map.put('V', 5);
		 map.put('X', 10);
		 map.put('L', 50);
		 map.put('C', 100);
		 map.put('D', 500);
		 map.put('M', 1000);
		 char[] arr = s.toCharArray();
		 int sum = 0;
			 for (int i = 0; i < arr.length; i++) {
				 if(i!=0){
					 if(arr[i-1]=='I'&&(arr[i] =='V'||arr[i]=='X')){					 
						 sum+=map.get(arr[i])-2;
					 }else if(arr[i-1]=='X'&&(arr[i]=='L'||arr[i]=='C')){
						 sum+=map.get(arr[i])-20;
					 }else if(arr[i-1]=='C'&&(arr[i]=='D'||arr[i]=='M')){
						 sum+=map.get(arr[i])-200;
					 }else{
						 sum+=map.get(arr[i]);						 
					 }
				 }else{
					 sum+=map.get(arr[0]);
				 }
				 
			 }
			 return sum;
	 }
  • 罗马数字转整数完成,现在要把整数转罗马数字(范围再3999内)
    有了上一题的经验,这一题不像一开始那样一点思路都没有,我的想法是把数字拆成个十百千四个位数,然后按照0到9匹配罗马字符串,再累加
public static String intToRoman(int num) {
		 int qian = num/1000*1000;//获取千位
		 int bai = (num-qian)/100*100;//获取百位
		 int shi = (num-qian-bai)/10*10;//获取十位
		 int ge = num-qian-bai-shi;//获取各位
		StringBuffer sb = new StringBuffer();
		int [] nums = {3000,2000,1000,900,800,700,600,500,400,300,200,100,90,80,70,60,50,40,30,20,10,9,8,7,6,5,4,3,2,1};
		String[] arrs = {"MMM","MM","M","CM","DCCC","DCC","DC","D","CD","CCC","CC","C","XC","LXXX","LXX","LX","L","XL","XXX","XX","X","IX","VIII","VII","VI","V","IV","III","II","I"};
		for (int i = 0; i < nums.length; i++) {
			if(qian==nums[i]){
				sb.append(arrs[i]);
			}
			if(bai==nums[i]){
				sb.append(arrs[i]);
			}
			if(shi==nums[i]){
				sb.append(arrs[i]);
			}
			if(ge==nums[i]){
				sb.append(arrs[i]);
			}
		}
		return sb.toString();
    }

最终虽然完成了需求,但是代码写得太痛苦,因为匹配的数组太长了,一开始疏漏很多情况,代码的可读性差,再参考了评论区答案后,得出了比较好的解答

public String intToRoman(int num) {
        String s = "";
		int [] nums = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
		String[] arrs = {"M", "CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
		for (int i = 0; i < nums.length; i++) {
			while(num>=nums[i]){
				s+=arrs[i];
				num-=nums[i];
			}
		}
		return s;
    }  

这种方法,大大减少了代码量,性能提升也很明显,原先的程序要耗时80ms,现在只要56ms,看来写代码最重要的还是思路,这一点的提升任重而道远

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值