Hackerrank Recursive Digit Sum(递归数位和)代码异常问题排查
问题原因排查
1. 数值类型溢出问题
你当前实现的核心错误是将拼接后的长字符串直接转换为long类型存储:
- 32位系统下
long类型最大仅支持存储2^31-1(约10位十进制数),64位long最大也仅支持19位十进制数 - 当拼接后的字符串长度超过对应位数时,会发生数值溢出,存储的数值是错误的,自然计算出的数位和和预期不符。你遇到的9875拼接4次得到16位数字,在32位编译环境下直接溢出,所以首次求和得到错误的46而非116。
- 且Hackerrank的官方测试用例会给出长度达上百位的字符串
n,根本不可能用普通数值类型存储。
2. SuperDigit函数逻辑错误
你的递归函数存在不可达代码和未定义行为:
int SuperDigit(long n){ long sum =0; if(n==0) return 0; else{ return sum= sum +(n%10 + SuperDigit(n/10)); // 此处直接return,后面代码永远不会执行 } // 以下代码为死代码,永远不会运行 if(sum>10){ return (sum%10 + SuperDigit(sum/10)); } // 存在分支没有返回值,属于未定义行为,运行结果不可控 }
当前函数只能实现单次数位和的计算,无法递归将结果收敛为个位数,同时分支返回不全的问题也会导致异常输出。
3. 不必要的字符串拼接操作
你完全不需要将字符串n拼接k次再计算数位和,根据数位和的数学性质:
字符串
n拼接k次后的总数位和 = 单次n的数位和 * k
直接计算这个乘积的超级数位即可,既避免了长字符串拼接的性能开销,也从根源上规避了数值溢出的问题。
修正方案
优化逻辑步骤
- 遍历输入字符串
n,逐个字符计算数位和得到single_sum - 计算总初始和
total = single_sum * k - 对
total计算超级数位(数根)即可 - 数根可以直接用公式计算:若
total == 0结果为0,否则若total %9 ==0结果为9,否则结果为total%9,不需要递归也能快速得到结果
修正后代码示例
#include <iostream> #include <string> using namespace std; // 正确的递归超级数位实现 long SuperDigit(long num) { if (num < 10) { return num; } long sum = 0; while (num > 0) { sum += num % 10; num /= 10; } return SuperDigit(sum); } int main() { string n; int k; cin >> n >> k; long single_sum = 0; // 直接遍历字符串计算单次数位和,不需要转数值 for (char c : n) { single_sum += (c - '0'); } long total = single_sum * k; cout << SuperDigit(total) << endl; return 0; }
上述代码针对n='9875'、k=4的用例,计算得single_sum=29,total=29*4=116,递归计算116的超级数位得到8,符合预期。
内容的提问来源于stack exchange,提问作者edw
相关产品推荐
相关产品推荐

