前引:其实我做完12题之后接着做这道题,我还是挺蒙的,看了眼难度,有点怀疑我的智商,但理清思路了之后,也不难,这两天有事情,就发布得少,今天是晚上打完英雄联盟躺在床上,惊醒,发现有好久没有发布了,不能再懒惰下去了,所以拖着疲惫的身体,写了一下吧
本次特点(如果某次题解,我觉得我特别棒,那我就会声明一下):
发布了一个非主流的新方法,至少我在LeetCode上没见过,你如果跟我想的一样的话,那我得好好夸你了,好了,下面正式开始
解题思路:
1.获取信息:(本来想直接略过的,因为我上一条博客在12题的时候已经解释得超级清楚了,但还是照顾你,写出来吧)
(1)获得了基础的罗马数字转换表
(2)从左往右读,左边的罗马字符对应的值小于右边的罗马字符的值
两者要一起看,值为右边的值减去左边的值
如:"IV","I"为1,"V"为5,"IV"为5 - 1 = 4
(3)从左往右读,左边的罗马字符对应的值大于等于右边的罗马字符的值
就会出现两种情况,我给鲜明的例子
第一种情况,如:"III","I"为1,"III"为1 + 1 + 1 = 3
第一种情况,如:"VIII","V"为5,"I"为1,"VIII"为5 + 1 + 1 + 1 = 8
(4)结果的大小在1到3999,闭区间
2.分析问题:其实我获取信息的时候已经精炼过一次了,已经够易懂了,我这次就不再分析一次了,平时我的分析问题环节都是十分精彩的,这次例外,主要是特别简单,没有这个环节,我觉得差了点什么,就没有删掉
3.示例查验:唯一给我的启发就是,让我知道了,从右往左读,比从左往右读简单,我觉得啊,平时我的示例查验环节也是十分精彩的
4.尝试编写代码(重要环节来临)
我想出来两种方法,其中一种,我觉得特别妙
(1)暴力法
由之前的示例启发,我觉得从右往左读要简单一点,每个人的想法不一样,有人觉得从左往右比较简单,所以,” 每个人眼里的代码都是不一样的,希望你可以找到属于自己的代码 “
通过基础的罗马数字转换表,它可以根据我在获取信息环节时总结出来的两种情况来获得答案,代码如下
class Solution {
public:
int romanToInt(string s) {
int res=0;
unordered_map<char,short>Roma{
{'I',1},{'V',5},{'X',10},{'L',50},{'C',100},{'D',500},{'M',1000}
};//基础罗马数字转换表
for(int i=s.size()-1;i>=0;i--){//从右往左遍历
if(i>0&&(Roma[s[i]]>Roma[s[i-1]])){//如果左边的罗马符号的值小于右边罗马符号的值
res=res+(Roma[s[i]]-Roma[s[i-1]]);
i--;
continue;
}
res+=Roma[s[i]];//如果左边罗马符号的值大于等于右边罗马符号的值
}
return res;
}
};
(2)乱匹风锤法
滑动窗口法和动态规划,它们的思想给了我启发
思路:我们知道,最多有四个字符作为一个整体来转换成一个整数,我给鲜明的例子
如:"VIII",这四个字符表示8,对吧
那么我们将字符的所有合法的组合形式都写出来存在容器种,然后,第一次取,我们取四个字符组成字符串去容器种查找
如果查到了,那就直接加上,如果没查到,那就取三个字符,再次查找
我们有保底机制,那就是当取一个字符时,肯定能查找到,所以,我叫它乱匹风锤法,致敬一下糖加三勺
class Solution {
public:
int romanToInt(string s) {
int res = 0;
unordered_map<string, int>Roma{
{"I",1},{"II",2},{"III",3},{"IV",4},{"V",5},{"VI",6},{"VII",7},{"VIII",8},{"IX",9},{"X",10},{"XX",20},{"XXX",30},{"XL",40},{"L",50},{"LX",60},{"LXX",70},{"LXXX",80},{"XC",90},{"C",100},{"CC",200},{"CCC",300},{"CD",400},{"D",500},{"DC",600},{"DCC",700},{"DCCC",800},{"CM",900},{"M",1000},{"MM",2000},{"MMM",3000}
};//将罗马字符的所有组合情况写入容器种
int size = s.size();//取s的大小
int i=0;//取字符的起点
while(i<=size-1){
res+=OP(s,Roma,i);
}
return res;
}
private:
int OP(string&s,unordered_map<string,int>&Roma,int& i){//注意,这里i用的是引用,这里改变i,i会整体改变的
int cap=4;//取字符的个数,每次都改变的
int res=0;
while(cap){
string tool=s.substr(i,cap);//用来存,取得的字符组合而成的字符串,所以叫他工具人(tool)
if(Roma.find(tool)!=Roma.end()){//如果查找到了,就直接加上,break,不用再继续循环了
res+=Roma[tool];
break;
}
cap--;//没找到就减少取字符的数目
}
i+=cap;//取得了之后,就移动i到合适的位置
return res;
}
};
(3)四指针法:我就不写了,大概思路跟乱匹风锤法异曲同工,但是没有前者简练,比较不推荐
最后:今天是疲惫了,这次比较偷懒,没有写得很详细,脸上无光,祝早睡
还是要提一嘴,纸上得来终觉浅,绝知此事要躬行