【LeetCode】1945. 字符串转化后的各位数字之和

题目描述

给你一个由小写字母组成的字符串 s ,以及一个整数 k 。
首先,用字母在字母表中的位置替换该字母,将 s 转化 为一个整数(也就是,‘a’ 用 1 替换,‘b’ 用 2 替换,… ‘z’ 用 26 替换)。接着,将整数 转换 为其 各位数字之和 。共重复 转换 操作 k 次 。
例如,如果 s = “zbax” 且 k = 2 ,那么执行下述步骤后得到的结果是整数 8 :
转化:“zbax” ➝ “(26)(2)(1)(24)” ➝ “262124” ➝ 262124
转换 #1:262124 ➝ 2 + 6 + 2 + 1 + 2 + 4 ➝ 17
转换 #2:17 ➝ 1 + 7 ➝ 8
返回执行上述操作后得到的结果整数。

示例 1:

输入:s = “iiii”, k = 1
输出:36
解释:操作如下:
转化:“iiii” ➝ “(9)(9)(9)(9)” ➝ “9999” ➝ 9999
转换 #1:9999 ➝ 9 + 9 + 9 + 9 ➝ 36
因此,结果整数为 36 。

示例 2:

输入:s = “leetcode”, k = 2
输出:6
解释:操作如下:
转化:“leetcode” ➝ “(12)(5)(5)(20)(3)(15)(4)(5)” ➝ “12552031545” ➝ 12552031545
转换 #1:12552031545 ➝ 1 + 2 + 5 + 5 + 2 + 0 + 3 + 1 + 5 + 4 + 5 ➝ 33
转换 #2:33 ➝ 3 + 3 ➝ 6
因此,结果整数为 6 。

提示:

1 <= s.length <= 100
1 <= k <= 10
s 由小写英文字母组成

方法一:模拟,取余整除法

思路:

  • 首先我设置了一个数组 nums,里面放置字符串 s 的数字转换,依次遍历字符串 s,将其转换为对应的数字;
  • 由于 k 至少为 1 ,因为可以对遍历数组,让数组中所有数字的个位和十位相加(使用整除和取余),此时已经完成了一次 k 操作, 因此 k --;
  • 接下来判断是否已经完成了操作,如果没有,则继续按照上述方法遍历,注意,当结果为个位数的话,就可以退出循环,因为个位数无论如何相加都等于它本身。

情况

  • 通过;

收获

  • 这一个题蛮简单的,由于我对很多 api 不太熟悉,用了最原始的方法(取余 + 整除)来计算各个位置的数字和,幸好取余的效率很高;
  • 我直接将字符串 -> 存放数字的数组 -> 操作一次变成整数 ,省略了将字符串 -> 数字字符串 -> 整数 ->操作一次 的步骤,虽然代码看起来冗长些,但速度应该快了点。

时间复杂度:O(n),由于 n <= 100 ,在最坏情况下, s 由 100 个 s 字母组成, 对应数字 19 ,则:

  • 第一次操作后,数字为 (1 + 9) * 100 = 1000,说明第一次操作后的数字范围在 [0, 1000] 之间,其中最大的数字和为 999;
  • 也就是说第二次操作的最大数字为 9 + 9 + 9 = 27 ,第二次操作后的数字范围为 [0, 27],其中最大的数字和为 19 ;
  • 说明第三次操作的最大数字为 1 + 9 = 10 ,第三次操作后的数字范围为 [0, 10] ,其中最大的数字和为 9,说明第四次操作后,一定会得到个位数的结果
  • 因此,循环最多执行 4 次,除了第一次循环处理的长度为字符串长度 n ,其余都小于 n,因此这一部分的时间复杂度看作 O(n),总的时间复杂度为 O(n);

空间复杂度:O(n),n 为字符串 s 的长度;
在这里插入图片描述

class Solution {
public:
    int getLucky(string s, int k) {
        int n = s.size();
        int sum = 0;
        vector<int> nums(n);
        for(int i=0; i<n; i++)    nums[i] = s[i] - 'a' + 1;
        for(auto& num : nums){
            while(num){
                sum += num % 10;
                num /= 10;
            }
        }
        k --;
        int res = sum;
        while(k){
            res = 0;
            while(sum){
                res += sum % 10;
                sum /= 10;
            }
            if(res < 10) break;
            sum = res;
            k --;
        }
        return res;
    }
};

方法二:模拟,使用字符串转换函数

思路:

  • 首先将字母字符串转换为数字字符串;
  • 开始遍历数字字符串,每个数字进行累加,当 满足操作次数 或 结果为个位数 ,结束循环。

情况

  • 通过;

收获

  • 方法二的思路更贴近于题目;
  • 灵活运行字符串函数
    • to_string :数字 -> 字符串;
    • stoi : 字符串 -> 数字;

时间复杂度:O(n),和方法一相同,不赘述;
空间复杂度:O(n), n 为字符串长度。

class Solution {
public:
    int getLucky(string s, int k) {
        string digits;
        for(auto& c : s) digits += to_string(c - 'a' + 1);

        for(int i=1; i<=k && digits.size()>1;i++){
            int sum = 0;
            for(auto& ch : digits)  sum += ch - '0';
            digits = to_string(sum);
        }
        return stoi(digits);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值