作者: hancao
介绍:本命年的前端工程师
微信:hancao97
背景
春节我从小年就开始请假,完完整整的休息了两周(如果这个文章有人看,请把羡慕两个字打在评论里 ,哈哈哈哈),那两周我本意是我要好好学习天天向上,努力锻炼强健体魄。然而后来发现这些都是扯淡!!!过年在家学习?不存在的,每天就是陪陪父母家人,和家里的小孩子玩。说来也奇怪,原来大学的时候,我不太喜欢小孩子,但是去年工作了,今年回家我就觉得小孩子好可爱,哇,眼睛那么清澈干净,小手小脚那么可爱,真的是让我这个老男人心都融化了,诶呀,我最喜欢小孩子了~(所有人都逃不过真香定律,俺也一样~)
所以,既然休息了这么久,我的心肯定早就飘到九霄云外了,我需要调整一下自己的状态开始新的一年,新的一年肯定要元气满满呀,于是从做两道leetcode开始吧,但是我这实力不行加上手都生了,必须选简单的(选简单的说的理直气壮),于是,这个罗马数字和数字的相互转换就深得我心,所以开始吧!!!
罗马数字与整数转换规则介绍
首先我先介绍一下罗马数字,也方便大家了解后续的题目。
罗马数字包含以下七种字符:I
, V
, X
, L
,C
,D
和 M
。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
上面就是罗马数字和整数的对应关系。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
于是,其实我们可以,修改一下前面的那个表。
字符 数值
I 1
IV 4
V 5
IX 9
X 10
XL 40
L 50
XC 90
C 100
CD 400
D 500
CM 900
M 1000
ok,我们有个这个映射规则,就可以开始做这两道算法题啦!
罗马数字转整数
我们先从简单的罗马数字转整数开始。
先举几个例子:
输入: "III"
输出: 3
输入: "IV"
输出: 4
输入: "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.输入: "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
ok,这道题其实很简单,整体思路就是一次对输入字符串的遍历,在遍历的过程中有两种情况:
- 前一个罗马字符比后一个罗马字符对应的整数小,我们就执行减法操作
- 前一个罗马字符比后一个罗马字符对应的整数大或者相等,我们就执行加法操作
ok!既然这到底思路如此简单,那就直接上代码吧~
var romanToInt = function(s) {
const ROMON_MAP = new Map([['I', 1],['V', 5],['X', 10],['L', 50],['C', 100],['D', 500],['M', 1000]]);
const S_LENGTH = s.length;
let resNum = 0;
let nextNum = 0;
let currentNum = ROMON_MAP.get(s[0]);
for(let index = 1;index < S_LENGTH;index++) {
nextNum = ROMON_MAP.get(s[index]);
if(currentNum < nextNum){
resNum -= currentNum;
} else {
resNum += currentNum;
}
currentNum = nextNum;
}
resNum += currentNum;
return resNum;
};
运行结果:
其实不是很good。我就很sad。
整数转罗马数字
这个就比之前的题目稍微难了一些,leetcode上面的难度也从简单变成了中等,其实也就还好,因为上文提到,我们有了一个新的映射关系!
字符 数值
I 1
IV 4
V 5
IX 9
X 10
XL 40
L 50
XC 90
C 100
CD 400
D 500
CM 900
M 1000
我们先举个例子吧:
输入: 3
输出: "III"
输入: 4
输出: "IV"
输入: 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.
输入: 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.
首先我们得思路是贪心算法,思想是这样的:
每一步都使用当前对应整数较大的罗马字符进行匹配,最后得到罗马数字表示就是长度最少的。
好的说干就干:
var intToRoman = function(num) {
const NUMS = [1000,900,500,400,100,90,50,40,10,9,5,4,1];
const ROMON_CHARS = ['M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I'];
let index = 0;
let romonResStr = '';
let temp = 0;
while(index < 13 && num > 0) {
temp = Math.floor(num/NUMS[index]);
if(temp>0){
romonResStr += ROMON_CHARS[index].repeat(temp);
num -= NUMS[index]*temp;
}
index++;
}
return romonResStr;
};
简单讲一下代码吧,首先我们会从较大得罗马字符进行匹配,于是,我建立了两个数组一个是NUMS列表,一个是ROMON_CHARS罗马字符列表,都是从大到小排列得,为什么选用的是数组,因为我在意他们的先后顺序,和之前那个算法不一样,所以之前那个算法我用的数据结构是Map。
之后我们进行了一些初始化,index对应NUMS和ROMON_CHARS的下标,romonResStr是结果字符串,temp变量。
然后开始循环,循环结束条件是index>=13或者num<=0。进入循环体,我们要看当前数值是否是NUMS[index]的整数倍,如果是表示现在的num还大于当前遍历中index指向罗马字符对应的数字,即temp>0。如果temp>0,那么我们就吧当前罗马字符重复temp次,追加到romonResStr中,并执行num -= NUMS[index]*temp。最后index++进入下一次循环。
最后执行结果大概是这样的:
ok,这个代码就讲完了。这两道题还是比较简单,适合新年练练手~
回顾Flag以及总结
诶呀,我之前还是立了很多flag的,今年要去努力实现的,看这个这个,学那个和那个,emmm,搬运以下,列出来吧:
做有主见,有执行力的工程师。
如2021的一月份一样,坚持六点半起床,每天至少两小时的学习时间,并每天锻炼身体30-90分钟【一周至少五次】。
对计算机基础知识的深入学习。【计算机组成原理,编译原理,操作系统等等】(长期,不限于2021)
vue3源码学习。
【英语水平需要加强…】,提升自己获取优质资料并学习能力。
输出12篇高质量博客。【但是我觉得高可能大佬觉得完全不行哈~】
100道leetcode算法题【一月份已完成15道】
提升算法和数据结构水平【系统地读书】(长期,不限于2021)
去西藏!
变成光,迪迦!【抱歉,不正经了!】
其实之前列的flag还是好多好多的,但是作为一个工程师这个职业工作已经半年了,感觉其实这是工作,工作的时候也有相应的责任,所以简要的把目标转化成以下几点:
1. 工作中完成高质量高效率的业务支持(工作责任感,这是要做到的最基础最基础的事情)
2. 生活中积极向上,有自己热爱的事情(比如去旅游!),并去做!
3. 个人成长上不局限自己,扩宽,加深,学习不限于前端,还包括计算机基础,以及各种软技能
4. 以及收获爱情就再好不过了,但是我感觉我还年轻,不着急
美好的祝愿
希望大家工作顺利!
希望大家健健康康!
希望大家开开心心!
希望大家都有自信有勇气!
希望大家都可以认识更多有温度的人!
希望大家都有热爱并向去追寻的目标!
希望大家(主要是我)找到命中注定的人!
希望世界和平!
...
新的一年的工作开始啦!!
专注!
加油呀!