(字符串,哈希) 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;
 
    }
};

 

posted @ 2019-07-25 22:36  爱学英语的程序媛  阅读(200)  评论(0编辑  收藏  举报