文章目录
- 一、题目
- 二、初级解法:顺序遍历字符串
- 我的解法(语法平平无奇)
- 语法接近
- 三、精妙解法:逆序遍历字符串
- 四、知识点:map和unordered_map的区别
LeetCode 第13题,罗马数字转整数;难度等级:简单。
知识点:map和unordered_map的区别
一、题目
二、初级解法:顺序遍历字符串
我的解法(语法平平无奇)
顺序遍历字符串是我们最自然想到的方法,我的解法如下:
class Solution {
private:
unordered_map<char, int> roman = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
public:
int romanToInt(string s) {
int length=s.size();
int sum=0;
for(int i=0;i!=length;i++){
int romanValue=roman[s[i]];
if(i!=length-1 && romanValue<roman[s[i+1]])
sum-=romanValue;
else
sum+=romanValue;
}
return sum;
}
};
语法接近
看到 if -else 就应该想到是否可以用 三目运算符 " ?:"来代替,进阶语法如下:
class Solution {
private:
unordered_map<char, int> roman = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
public:
int romanToInt(string s) {
int length=s.size();
int sum=0;
for(int i=0;i!=length-1;i++)
sum += (roman[s[i]]<roman[s[i+1]]) ? -roman[s[i]] : roman[s[i]];
sum += roman[s[length-1]];
return sum;
}
};
三、精妙解法:逆序遍历字符串
思路:从右到左逆序遍历字符串,记录当前遇到的最大的数字;遇到更大的就加,并且更新最大数,遇到小的就减。代码如下:
class Solution {
private:
unordered_map<char, int> roman = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
public:
int romanToInt(string s) {
int length=s.size();
int sum=roman[s[length-1]]; //初始化sum为最后一个字符的值
int max=roman[s[length-1]]; //初始化最后一个字符为最大字符
for(int i=length-2;i>=0;i--){
int value=roman[s[i]];
sum += (value<max)? -value : value;
max = (value<max)? max : value; //更新最大值
}
return sum;
}
};
四、知识点:map和unordered_map的区别
unordered_map就是通俗意义上的hash map,map和unordered_map的底层实现原理具有很大差距,因此它们的使用场景也不尽相同。二者区别如下:
map | unordered_map | |
---|---|---|
是否有序 | 有序 | 无序 |
底层实现 | 红黑树 | 哈希表 |
查找 | 块,Average: O(1) , Wrost Cse: O(n) | log(n) |
插入 | 块,Average: O(1) , Wrost Cse: O(n) | log(n) + 平衡二叉树所用时间 |
删除 | 块,Average: O(1) , Wrost Cse: O(n) | log(n) + 平衡二叉树所用时间 |
使用场景 | 多次无序查找 | 需要有序性或者对单次查询有时间要求的应用场景下 (单次查询时map可以确保良好的最坏情况运行时间) |