(字符串,哈希) leetcode 8. atoi,12. Integer to Roman
思路:判断各种边界条件。
1)首先过滤字符串前面的空格,即找到第一个不为空格的字符;
2)如果第一个字符是+或-,设置flag值;
3)接下来的字符如果在'0' - '9' 范围内,则转换为数字,否则结束循环; 注意上一步中,如果结果已经大于INT_MAX或小于INT_MIN,则直接返回INT_MAX或INT_MIN;
4)如果过滤掉空格后的字符不是一个有效的整数字符,则返回0;
5)整数之后可能有多余的其他字符,可以忽略不计。
class Solution { public: int myAtoi(string str) { int s = str.size(); if(s==0) return 0; int i=0, flag=1, cur; //用i遍历,flag存储正负号 long ans = 0; //计算数字的值,因为可能超出int边界,故定义为long while(i<s && str[i] == ' ') //过滤前面的空格 i++; if(str[i]=='-' || str[i] == '+'){ //处理 + 和 - if(str[i] == '-') flag = -1; i++; } while(i<s && str[i]>='0' && str[i]<='9'){ cur = str[i] - '0'; ans = ans*10 + cur; if(ans * flag < INT_MIN) return INT_MIN; if(ans * flag > INT_MAX) return INT_MAX; i++; } return ans*flag; } };
题意是将数字转化为罗马数字。因为通常情况下,罗马数字中小的数字在大的数字的右边。所以用贪心来做,将输入的数字num 与1000比较大小,若比1000大,则将M放入str中,再将num-1000的数值再与900比较,以此类推....
但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX;所以,4,9,40,90,400,900也需要放到哈希表中。
注意输入数字大小在1-3999之间。
class Solution { public: string intToRoman(int num) { vector<int> value = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5,4,1}; vector<string> roman = {"M", "CM", "D","CD","C","XC","L","XL","X","IX","V","IV", "I"}; string str; int i = 0; while(num>0 && i<value.size()){ if(num >= value[i]){ str += roman[i]; num -= value[i]; } else i++; } return str; } };
class Solution { public: int romanToInt(string s) { unordered_map<string, int> mp = {{"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}}; int r = 0, i = 0; while(i<s.size()){ string two = s.substr(i, 2); string one = s.substr(i, 1); if(mp[two]){ r += mp[two]; i+=2; } else if(mp[one]){ r += mp[one]; i++; } } return r; } };
class Solution { public: int romanToInt(string s) { unordered_map<string, int> mp = {{"I",1}, {"V", 5}, {"X", 10}, {"L", 50}, {"C", 100}, {"D", 500}, {"M", 1000}}; int r = mp[s.substr(0,1)]; for(int i=1; i<s.size(); ++i){ if( mp[s.substr(i-1,1)] < mp[s.substr(i,1)] ) // 类似"IV"的情况, 因为r多加了一个mp[s.substr(i-1,1)],所以要减去 r += mp[s.substr(i,1)] - 2 * mp[s.substr(i-1,1)]; else r += mp[s.substr(i,1)]; } return r; } };
思路:
注意:res[high] += ans/10; 高位需要加上自身。对于string类型字符串,假如是 str1 = "abcdef", str1[0]为a,而str1[str1.size()-1]为f ;但是对于 vector和数组,若res = {0,1,2,3,4,5}, 则 res[0] 为5,res[res.size()-1] 为0,所以对于这个两重循环,从两个字符串的末尾开始遍历,存储到vector类型的res的高位,所以再排除开头的0时,需要直接从res的索引为0开始,往字符串r中添加。
class Solution { public: string multiply(string num1, string num2) { if(num1.size()==0 || num2.size()==0) return "0"; int s1 = num1.size(), s2 = num2.size(); vector<int> res(s1+s2, 0); string r=""; int low=0, high = 0, ans=0; for(int i=s1-1; i>=0; --i){ for(int j=s2-1; j>=0; --j){ low = i+j+1, high = i+j; ans = (num1[i]-'0')*(num2[j]-'0') + res[low]; //加上进位 res[low] = ans%10; //模10取余 res[high] += ans/10; //储存进位 } //res索引大的存储的是数值的低位 } for(int a: res) if(!r.empty() || a!=0) r.push_back(a+'0'); return r.empty()? "0": r; } };
class Solution { public: string multiply(string num1, string num2) { if(num1.size()==0 || num2.size()==0 || num1=="0" || num2=="0") return "0"; int s1 = num1.size(), s2 = num2.size(); vector<int> res(s1+s2, 0); string r=""; int low=0, high = 0, ans=0; for(int i=s1-1; i>=0; --i){ for(int j=s2-1; j>=0; --j){ low = i+j+1, high = i+j; ans = (num1[i]-'0')*(num2[j]-'0') + res[low]; //加上进位 res[low] = ans%10; //模10取余 res[high] += ans/10; //储存进位 } } int k = 0; while(res[k]==0 && k<res.size()) k++; for(int i = k; i<res.size(); ++i) r += char(res[i]+'0'); return r.empty()? "0": r; } };