我已经正确编写了用于获取大量(长而长)的超数字的程序,但是由于超时和中止调用,似乎无法通过某些情况。请提出一些优化措施以改善程序的运行时间:
int superDigit(long long m) {
int d=countDigit(m);
if(d==1){
return m;
}
long s=sumDigit(m);
return superDigit(s);
}
//utility functions to calculate digit count and sum of digits
int countDigit(long long n)
{
int count = 0;
while (n != 0) {
n = n / 10;
++count;
}
return count;
}
long sumDigit(long long n)
{
long sum = 0;
while (n != 0) {
sum += n % 10;
n = n / 10;
}
return sum;
}
理论:超数字由以下规则定义:
例如:
答案 0 :(得分:4)
每个superDigit
调用仅对数字循环一次,并避免递归可以使速度更快。像这样:
long long superDigit(long long m) {
long long sum;
while(true) {
sum = 0;
while(m != 0) {
sum += m % 10;
m /= 10;
}
if(sum >= 10)
m = sum;
else
break;
}
return sum;
}
如果您需要支持重复序列,例如593次10次(对于long long
而言通常太大),则可以添加一个包装器,如下所示:
long long superDigit(long long m, int times) {
long long r = superDigit(m) * times;
if(r >= 10) r = superDigit(r);
return r;
}
对于足够小以适合long long
的数字,您可以检查其是否有效。示例:
superDigit(148148148) == superDigit(148, 3)
如果需要支持不是 重复序列的大数字,则可以添加另一个重载,将数字作为std::string
:
long long superDigit(const std::string& m) {
long long sum = 0;
for(auto d : m) sum += d - '0';
if(sum >= 10) return superDigit(sum);
return sum;
}
您可以检查它是否也获得了与以前的重载之一相同的结果:
superDigit(593, 10) == superDigit("593593593593593593593593593593")
答案 1 :(得分:0)
我认为您正在中止要求m值!如果m的值为0,则递归将继续存在。而且,如果m的值可以为负,那么也要注意负值的问题。
请检查!
int superDigit(long long m) {
if(m<=9)return m; // handling case 0
int d=countDigit(m);
if(d==1){
return m;
}
long s=sumDigit(m);
return superDigit(s);
}
答案 2 :(得分:0)
您的代码有一个'0'问题。它进入一个无限循环,如果调用堆栈溢出(如果编译器没有消除尾部递归的话),该循环将终止。 完全不需要数字计数助手功能
int superDigit(long long m) {
if(m<10){
return m;
}else{
int s = 0;
do {
s += m % 10;
m = m / 10;
}while (m > 0);
return superDigit(s);
}
}
您可以通过将整个过程放在一个循环中来消除递归。
int superDigit(long long m) {
while (m >9){
int s = 0;
do {
s += m % 10;
m = m / 10;
}while (m > 0);
m = s;
}
return m;
}
但是递归看起来有些自我解释,现代编译器也应该能够消除尾递归。