问题描述
我写了这段代码,它使用递归计算一个整数中有多少个 1。 N 必须小于 9 位。我似乎无法找到我的代码有什么问题以及为什么它不起作用。如果有人能告诉我我哪里出错了,我将不胜感激。
#include <stdio.h>
#include <assert.h>
int count_ones(int n);
int main()
{
assert(count_ones(1001)==2);
}
int count_ones(int n)
{
int sum = 0;
int x;
if(n == 0)
{
return sum;
}
else if(n > 999999999)
{
return sum;
}
else if(n <= 999999999)
{
x == n%10;
if (x == 1)
{
sum = sum + 1;
count_ones(n/10);
}
else
{
count_ones(n/10);
}
}
return sum;
}
解决方法
您没有将当前的 sum
与递归调用的结果相结合。因此,您只计算最后一位数字,其他所有计数都将被丢弃。
int count_ones(int n) {
if (n == 0 || n > 999999999) {
return 0;
} else if (n % 10 == 1) {
return 1 + count_ones(n / 10);
} else {
return count_ones(n / 10);
}
}
,
太复杂了。
正确的做法如下:
int count_ones(int n)
{
return n? (n%10 == 1) + count_ones(n/10) : 0;
}
为了完整起见,这是一个迭代(非递归)解决方案。
int count_ones(int n)
{
int total=0;
for(;n; n/=10,total += (n%10==1));
return total;
}
,
@Barmar 的回答让您知道如何解决您的方法。这是另一种方法,它利用了尾递归的优势,可以由编译器展开到循环中。这种方法是使用累加器 (acc
) 来计数,并且只会返回一次。
int count_ones_rec(int n,int acc)
{
if (n == 0)
return acc;
return count_ones_rec(n / 10,acc + (n % 10 == 1));
}
这可以包装在一个函数中,如:
int count_ones(int n)
{
/* additional checks on `n` if needed */
return count_ones_rec(n,0);
}
,
对于初学者来说,有一个错字
x == n%10;
你的意思是赋值而不是比较
x = n%10;
在这些函数调用中
if (x == 1)
{
sum = sum + 1;
count_ones(n/10);
}
else
{
count_ones(n/10);
}
您没有使用递归调用的返回值
count_ones(n/10);
此外,由于函数参数具有签名类型 int
,因此用户可以向函数传递一个负数。在这种情况下,函数将返回错误的结果。
注意这种限制
else if(n > 999999999)
没有意义。用户可以为 int
类型的对象输入任意数量的可接受值范围。
该函数可以如下所示,如下面的演示程序所示。
#include <stdio.h>
size_t count_ones( int n )
{
const int Base = 10;
return n == 0 ? 0 : ( n % Base == ( n < 0 ? -1 : 1 ) ) + count_ones( n / Base );
}
int main(void)
{
printf( "%zu\n",count_ones( -11 ) );
printf( "%zu\n",count_ones( 11 ) );
return 0;
}
程序输出为
2
2