常写算法,多动脑,不会老!
理论太枯燥,先来个实际场景,场景取自 LeetCode 12 —— Integer to Roman 问题。要求能把 1~3999 的整型数字转化罗马数字。
先科普一下罗马数字,如下表所示:
罗马字符 | I | V | X | L | C | D | M |
---|---|---|---|---|---|---|---|
对应的阿拉伯数字 | 1 | 5 | 10 | 50 | 100 | 500 | 1000 |
需要注意的是,罗马数字同一数码最多出现三次,也就是说有一些数字比较特殊,例如:4——IV,9——IX,400——CD(右加左减的原则)。
代码示例:
string intToRoman(int num) {
vector<int> numPattern{1000,900,500,400,100,90,50,40,10,9,5,4,1};
vector<string> strPattern{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
string romanStr = "";
for (size_t i = 0; i < numPattern.size(); i++) {
while (num >= numPattern[i]) {
num -= numPattern[i];
romanStr += strPattern[i];
}
}
return romanStr;
}
从上述代码可以看出,把一些比较特殊的整型数字点和对应的罗马字符串都列举出来,利用贪婪算法进行匹配映射,代码十分简洁,且运行效率也较高。
简要科普一下贪婪算法的基本思路和算法过程
贪婪算法的基本思路:
从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到某算法中的某一步不能再继续前进时,算法停止。当然,该算法也存在一些问题:
1. 不能保证求得的最后解是最佳的;
2. 不能用来求最大或最小解问题;
3. 只能求满足某些约束条件的可行解的范围。
实现该算法的过程:
从问题的某一初始解出发;
while 能朝给定总目标前进一步 do
求出可行解的一个解元素;
由所有解元素组合成问题的一个可行解;
当然,对于 Integer to Roman 问题,使用贪婪算法再合适不过了。