[解题报告] 《算法零基础100讲》(第27讲) 字符串算法(七) - 高精度


前言

跟着英雄哥打卡第二十七天
[专题跳转->《算法零基础100讲》]
[万人千题社区跳转]


一、千位分隔数

跳转力扣:1556. 千位分隔数

难度:★☆☆☆☆

说明:首先获取数字的长度(可用转换字符串求长度偷懒,也可以先循环求出),从后面往前数,每3个数加一个小数点,加小数点的时候注意前面还有没有数,用当前数n即可判断

代码如下(示例):

class Solution {
public:
    string thousandSeparator(int n) {
        if (n == 0) return "0";
        int t = to_string(n).size();
        string res;
        int cnt = 0;
        while (n) {
            res += to_string(n % 10);
            n /= 10;
            cnt ++;
            if (!(cnt % 3) && n) { // 插入'.'的时候需要特殊判断
                res += '.';
            }
        }
        reverse(res.begin(), res.end()); // 由于是从后往前进行插入,
        								// 最后要转回来
        return res;
    }
};

二、字符串转化后的各位数字之和

跳转力扣:1945. 字符串转化后的各位数字之和

难度:★☆☆☆☆

说明:循环求得字母转为对应数字后的字符串【将"abc"转换为"123"】,后进行k次循环操作,将各位数相加,得出结果

代码如下(示例):

class Solution {
public:
    int getLucky(string s, int k) {
        string t;
        for (int i = 0; i < s.size(); i ++) {
            t += to_string(s[i] - 'a' + 1); // 'a' -> '1'
        }
        int sum;
        while (k --) {
            sum = 0;
            for (int i = 0; i < t.size(); i ++) { '11' -> 11
                sum += t[i] - '0';
            }
            t = to_string(sum);
        }
        return sum;
    }
};

三、字符串中第二大的数字

跳转力扣:1796. 字符串中第二大的数字

难度:★☆☆☆☆

说明:进行排序去重操作,以便确认能不能找到第二大的数,从小到大遍历找到第二大的数即可,注意字符与数字之间的转换,以及可以用isdigit()函数筛选数字,最后返回第二大数_2,不需要对是否能找到第二大数进行特殊判断,原因是一开始对第一第二大的数已经赋值为-1

代码如下(示例):

class Solution {
public:
    int secondHighest(string s) {
        int _1 = -1, _2 = -1;
        // 排序+去重
        sort(s.begin(), s.end());
        s.erase(unique(s.begin(), s.end()), s.end());
        
        for (int i = 0; i < s.size(); i ++) { // 查找第二大值_2
            if (isdigit(s[i]) && s[i] - '0' > _1) { 
                _2 = _1;
                _1 = s[i] - '0';
            }
            else if(isdigit(s[i]) && s[i] - '0' > _2) {
                _2 = s[i] - '0';
            }
        }
        return _2;
    }
};

三、最小时间差

跳转力扣:539. 最小时间差

难度:★☆☆☆☆

说明:minute()函数:求得该时间的分钟数;排序后循环遍历相邻两个数值的差值理论上最小值,用minn值维护,另外由于时间循环的特殊性,需要对最小与最大值的差值做特殊判断,找到最小值

代码如下(示例):

class Solution {
public:
    int minute(string s) {
        return (s[0] - '0') * 600 + (s[1] - '0') * 60 + (s[3] - '0') * 10 + (s[4] - '0');
    }
    int findMinDifference(vector<string>& timePoints) {
        if (timePoints.size() > 1440) // 24*60=1440 
            return 0;				// 若大于该数则必有重复
        vector<int> time(timePoints.size()); // 记录分钟数的数组
        for (int i = 0; i < timePoints.size(); i ++) {
            time[i] = minute(timePoints[i]);
        }
        sort(time.begin(), time.end());
        int minn = INT_MAX;
        for (int i = 1; i < time.size(); i ++) {
            minn = min(minn, time[i] - time[i - 1]);
            if (minn == 0)
                return 0;
        }
        // 由时间循环性,需要对最后一个数据进行特殊判断
        return min(minn, 1440 + time[0] - time[time.size() - 1]);
    }
};

四、罗马数字转整数

跳转力扣:13. 罗马数字转整数

难度:★★☆☆☆

说明:dict哈希表存储罗马数字对应数值,从左往右判断对应罗马数字是否小于下一位的罗马数字,若小于则减去罗马数字对应数值,若大于则加上对应数值(惊奇的发现在if判断语句加上i < s.size() - 1 后执行用时少些许,最后一位一定是加)

代码如下(示例):

class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> dict{{'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}};
        int ans = 0;
        for (int i = 0; i < s.size(); i ++) {
            if (i < s.size() - 1 && dict[s[i]] < dict[s[i + 1]]) { // 左减
                ans -= dict[s[i]];
            }
            else ans += dict[s[i]]; // 右加
        }
        return ans;
    }
};

六、整数转罗马数字

跳转力扣:12. 整数转罗马数字

难度:★★☆☆☆

说明:先用pair从大到小存储可能的罗马数字组合体,循环遍历数组找到大于该罗马值的数,即可减去该罗马数字对应的数值,同时将该罗马值加入到答案中,直至num减到0即表示结束

代码如下(示例):

pair<int, string> dict[] = {
{1000, "M"}, {900,  "CM"}, {500,  "D"}, {400,  "CD"},
 {100,  "C"}, {90,   "XC"}, {50,   "L"}, {40,   "XL"},
  {10,   "X"}, {9,    "IX"}, {5,    "V"}, {4,    "IV"},
   {1,    "I"}};

class Solution {
public:
    string intToRoman(int num) {
        string ans;
        for (auto p: dict) {
            while (num >= p.first) {  // 找到大于罗马组合体的数
                num -= p.first;
                ans += p.second;
            }
            if (num == 0) {
                break;
            }
        }
        return ans;
    }
};

七、字符串压缩

跳转力扣:面试题 01.06. 字符串压缩

难度:★★☆☆☆

说明:从前往后遍历,若当前字符与下一个字符不同时,则压缩,压缩后计数记得初始化,若相同则计数+1,直至与下一个不相同进行压缩

代码如下(示例):

class Solution {
public:
    string compressString(string s) {
        string ans;
        int cnt = 1;
        for (int i = 0; i < s.size(); i ++) {
            if (s[i] != s[i + 1]) { // 压缩
                ans += s[i];
                ans += to_string(cnt);
                cnt = 1;
            }
            else cnt ++;
        }
        return ans.size() < s.size() ? ans: s;
    }
};

八、字符串相加

跳转力扣:415. 字符串相加

难度:★★★☆☆

说明:大数相加模板如下:为方便进位计算,从小位开始相加,可先将加数逆转后再从左往右相加,最后记得再反转回来

代码如下(示例):

class Solution {
public:
    string addStrings(string num1, string num2) {
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        string num3;
        int t = 0;
        for (int i = 0; i < num1.size() || i < num2.size(); i ++) {
            if (i < num1.size()) t += num1[i] - '0';
            if (i < num2.size()) t += num2[i] - '0';
            num3 += t % 10 + '0';
            t /= 10;
        }
        if (t) num3 += t % 10 + '0';
        reverse(num3.begin(), num3.end());
        return num3;
    }
};

九、二进制求和

跳转力扣:67. 二进制求和

难度:★★★☆☆

说明:与上体相似,套模板类比即可

代码如下(示例):

class Solution {
public:
    string addBinary(string num1, string num2) {
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        string num3;
        int t = 0;
        for (int i = 0; i < num1.size() || i < num2.size(); i ++) {
            if (i < num1.size()) t += num1[i] - '0';
            if (i < num2.size()) t += num2[i] - '0';
            num3 += t % 2 + '0';
            t /= 2;
        }
        if (t) num3 += t % 2 + '0';
        reverse(num3.begin(), num3.end());
        return num3;
    }
};

十、检查某单词是否等于两单词之和

跳转力扣:1880. 检查某单词是否等于两单词之和

难度:★★★☆☆

说明:将’a’转换为’0’:‘a’-‘a’+‘0’==‘0’

代码如下(示例):

class Solution {
public:
    int stoiPlus(string s) {
        string res;
        for (int i = 0; i < s.size(); i ++) {
            res += s[i] - 'a' + '0'; // 'a' -> '0'
        }
        return stoi(res);
    }
    bool isSumEqual(string firstWord, string secondWord, string targetWord) {
        return stoiPlus(firstWord) + stoiPlus(secondWord) == stoiPlus(targetWord);
    }
};

十一、字符串相乘

跳转力扣:43. 字符串相乘

难度:★★★☆☆

说明:num1从右往左的每一位分别乘num2从右往左的每一位,例如先取出num2最后一位k1,然后num1从右往左遍历每一位,与k相乘的结果记录在cur字符串中,遍历完后可得到num1与k相乘的结果,然后取出num2倒数第二位k2,再与num1从右往左每一位相乘,得到的新的cur与上一位相乘结果cur相加,直至遍历到num2第一位,其间一直累加cur得到最后所求结果num3

代码如下(示例):

class Solution {
public:
    string multiply(string num1, string num2) {
        string num3 = "0";
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        for (int i = 0; i < num2.size(); i ++) {
            string cur = "";
            int k = num2[i] - '0';
            for (int j = 0; j < i; j ++) cur += '0';
            for (int j = 0, t = 0; j < num1.size() || t; j ++) {
                if (j < num1.size()) t += (num1[j] - '0') * k;
                cur += t % 10 + '0';
                t /= 10;
            }
            reverse(cur.begin(), cur.end());
            while (cur.back() == 0 && cur.size() > 1) cur.pop_back(); 
            num3 = add(num3, cur);
        }
        // 比较笨的删除前置零的方法
        reverse(num3.begin(), num3.end());
        while (num3.back() == '0' && num3.size() > 1) num3.pop_back(); 
        reverse(num3.begin(), num3.end());
        return num3;
    }
    // 大数相加模板
    string add(string num1, string num2) {
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        string num3;
        int t = 0;
        for (int i = 0; i < num1.size() || i < num2.size(); i ++) {
            if (i < num1.size()) t += num1[i] - '0';
            if (i < num2.size()) t += num2[i] - '0';
            num3 += t % 10 + '0';
            t /= 10;
        }
        if (t) num3 += t % 10 + '0';
        reverse(num3.begin(), num3.end());
        return num3;
    }

};

十二、整数转换英文表示

跳转力扣:273. 整数转换英文表示

难度:★★★☆☆

说明:很特别的一道题,建议直接跳转官方解答!
【官方】整数转换英文表示

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值