刷题练习——84. 数字魔法的加一操作

95 阅读3分钟

以下为题目描述

问题描述

数字魔法师小U发现了一种特殊的数字变换魔法。这个魔法可以对一个数字字符串进行"进位"操作。每次操作规则如下:

  • 对字符串中的每个数字进行加一操作
  • 当某位数字为9时,加一后变成 0,并在前面补 1

例如:

  • "798" 经过一次操作变成 "8109"(7→8, 9→0并向前增加一个1, 8→9)
  • "999" 经过一次操作变成 "101010"

现在给定一个数字字符串 num_str(长度为n)和操作次数 k,请计算经过 k 次操作后得到的最终结果。由于结果可能非常大,请将答案对 1000000007 (10^9 + 7) 取模。

输入

  • 第一行包含两个整数 n 和 k(1 ≤ n ≤ 50, 1 ≤ k ≤ 100)
  • 第二行包含一个长度为n的数字字符串 num_str,仅由数字0-9组成

返回

  • 返回一个整数,表示最终结果对 1000000007 取模后的值

测试样例

样例1:

输入:n = 3 ,k = 1 ,num_str = "798"
返回:8109
解释:798 经过一次操作变成 8109

样例2:

输入:n = 3 ,k = 3 ,num_str = "798"
返回:103221

  • 第一次操作:798 → 8109
  • 第二次操作:8109 → 92110
  • 第三次操作:92110 → 103221

样例3:

输入:n = 4 ,k = 3 ,num_str = "7989"
返回:10322132

解决方案

public class Main {
    public static int solution(int n, int k, String num_str) {
        final int MOD = 1000000007;
        StringBuilder currentNumber = new StringBuilder(num_str);

        for (int op = 0; op < k; op++) {
            StringBuilder newNumber = new StringBuilder();
            int length = currentNumber.length();

            for (int i = 0; i < length; i++) {
                char ch = currentNumber.charAt(i);
                if (ch == '9') {
                    // 数字为 '9',加一后变成 '0',并在前面补 '1' 
                    newNumber.append('1');
                    newNumber.append('0');
                } else {
                    // 数字加一操作
                    char incrementedDigit = (char) (ch + 1);
                    newNumber.append(incrementedDigit);
                }
            }
            currentNumber = newNumber;
        }

        // Convert the final number to integer modulo MOD
        String finalNumberStr = currentNumber.toString();
        int result = 0;
        for (int i = 0; i < finalNumberStr.length(); i++) {
            result = (int) ((result * 10L + (finalNumberStr.charAt(i) - '0')) % MOD);
        }

        return result;
    }

    public static void main(String[] args) {
        // You can add more test cases here
        System.out.println(solution(3, 1, "798") == 8109);
        System.out.println(solution(3, 3, "798") == 103221);
    }
}

代码解释

  1. 执行 k 次操作
for (int op = 0; op < k; op++) {
    StringBuilder newNumber = new StringBuilder();
    int length = currentNumber.length();

    for (int i = 0; i < length; i++) {
        char ch = currentNumber.charAt(i);
        if (ch == '9') {
            // 数字为 '9',加一后变成 '0',并在前面补 '1'
            newNumber.append('1');
            newNumber.append('0');
        } else {
            // 数字加一操作
            char incrementedDigit = (char) (ch + 1);
            newNumber.append(incrementedDigit);
        }
    }
    // 更新当前数字为新生成的数字
    currentNumber = newNumber;
}

• 外层循环执行 k 次操作。

• 内层循环遍历当前数字字符串的每一位,对每个字符进行判断和处理:

1)如果字符为 '9'

(1)根据规则,将 '9' 加一后变成 '0',并在前面补 '1'

(2)具体操作是先 append('1'),再 append('0'),即将 '9' 变成 '10'

2)如果字符不是 '9'

(1)将字符的 ASCII 码值加一,得到加一后的字符

(2)例如,字符 '7' 加一后变成 '8'

(3)完成一次操作后,更新 currentNumber 为新生成的数字字符串,为下一次操作做准备

  1. 将最终的数字字符串转换为整数并取
String finalNumberStr = currentNumber.toString();
int result = 0;
for (int i = 0; i < finalNumberStr.length(); i++) {
    result = (int) ((result * 10L + (finalNumberStr.charAt(i) - '0')) % MOD);
}

return result;

• 将 currentNumber 转换为字符串 finalNumberStr

• 使用 result 来存储最终的结果,初始化为 0

• 遍历 finalNumberStr 的每一位,将其转换为数字,并按照高精度计算的方法,逐位构造数字,同时在每一步都取模,防止溢出

(1)result * 10L:将当前结果左移一位(乘以 10)

(2)finalNumberStr.charAt(i) - '0':将字符转换为对应的数字

(3)result = (result * 10L + digit) % MOD:更新结果并取模