leetCode第十二题和十三题,整数与罗马数的相互转换,JavaScript实现

本文章的源码存放到github上,感兴趣的可以去查看:罗马数转整数整数转罗马数

         讲到整数与罗马数相互转换这道题,其实这道题在读大学的时候做acm也是一道经典的题。为了容易理解,我先从第十三题罗马数转整数这道题开始讲起。

        首先第十三题的题目是这样说的:

        下面的示例是这样的:

        第一眼看其实就能看出这道题的一种解题方法是暴力解题法,该解题是利用正则表达式,解题思路是用一个对象储存个位上1到9的各种对应的罗马数字、十位上10到90的各种对应罗马数字、百上100到900的各种对应的罗马数字,以此类推。最后通过正则表达式来使输入的罗马数变成一个数组,每个数组的元素则从左往右对应整数的位数,利用储存罗马数的对象来得出最后总和的结果。最后结果如下:

        虽然说暴力解题一时爽,但是显得代码十分的冗长。这里的时间复杂度为O(n),空间复杂度为o(n),这里的空间复杂度为O(n)是取决于正则返回的数组长度。其实这个暴力方法笨就本在其实对象里有很多属性是可以复用的,根本就不需要写那么多个属性出来。那如何复用呢?我们知道罗马数里1到1000是由下面这几个字母组成的,分别:

I、V、X、L、C、D、M

        所以我们的对象就储存这六个属性所对应的值就可以了。那如何转换呢?我们只需要对函数传过来的字符串进行遍历,如果当前字符串所对应的值小于下一个字符串所对应的值我们就能知道当前字符串肯定是I,而我们的算法是判断当初字符串对应的值是否大于下一个值,是的话就把当前值累加,不是的话减掉当前值,这样我们就可以不用正则表达式和在对象里存多个属性就能解得此题:

        换了新方法后在空间的上的速度快了不少,主要是少用了一个正则表达式。说完罗马数转整数,下面难度进阶一点,讲整数转罗马数。既然已经知道了第二种的解法,其实可以利用第二种解发稍微变通一下就变成了第十二题的解法。我们可以把对象里的罗马字符属性名换成整数为属性名,属性值为罗马字符串。然后用一个数组储存对象里的属性名,随后利用双指针对数组进行遍历,如果传过来的参数值大于数组最后一位数,则把当前下标对应的罗马数拼接到一个字符串遍历上,然后传过来的参数减掉比较的数,直到传过来的参数的值小于1为止。代码如下所示:

        这里我认为有两个注意点就是为什么对象和上面的对象不一样,比上面的对象多了好几个属性。这里主要是简化循环内的判断次数,减少空间复杂度。有些代码如果能执行一次就尽量执行一次,这样对空间和时间都有不少的提升。第二点就是我这里的数组是直接写值进去的,而不是利用解构和Object.keys来对对象里的属性名赋值到数组中,这是因为Object.keys源码里执行了两层for循环,十分的耗时,而数组解构其实是利用到了slice()函数,也会对内部进行一次遍历,所以用这种方法的话时间和空间复杂度会非常的高,不太推荐使用。

        除了这种方法以外,还有一种方法的时间和空间复杂度都为1,就是暴力解题法,如下:

        不过想不明白的是最快160ms的那个代码是这样写的:

        其实他用了两层for循环,时间复杂度妥妥的,只不过测试的样本太少,使得他的速度有可能很快。就好比在数据量很少且数据是有序的情况时,冒泡排序甚至比快速排序还要快。

发布了72 篇原创文章 · 获赞 44 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/Tank_in_the_street/article/details/90314725