【问题标题】:Simplifying a Recursive Function简化递归函数
【发布时间】:2021-12-17 04:42:50
【问题描述】:

我有一个递归函数,它将整数范围内的所有偶数相加。我现在的代码可以正常工作,但看起来可以简化。我尝试将递归函数放在不同的位置,但每次我得到错误的答案。你们能告诉我如何缩短我的代码吗?

int sum_evens(int range_start, int range_end)
{
   int even_sum = 0; /* The inclusive sum of all even numbers within  */
                     /* whole number range                            */

   printf("\n   Entering sum function for range %d to %d", 
                                            range_start, range_end);
                                            
   if(range_start <= range_end)
   {
      if(is_even(range_start) == 0)
      {
         printf("\n      Adding: %d", range_start);
         even_sum = sum_evens(range_start + 1, range_end);
         even_sum += range_start;
      }
      else
      {
         printf("\n      Skipping: %d", range_start);
         even_sum = sum_evens(range_start + 1, range_end);
      } 
  }

  printf("\n   Exiting sum function for range %d to %d with result: %d",
     range_start, range_end, even_sum);
  
 return even_sum;

}

我基本上是想只有这条线 (even_sum = sum_evens(range_start + 1, range_end);)

【问题讨论】:

  • 你可以用数学来简化它。忘记所有关于算法和递归函数和循环的事情,找到一个可以直接返回结果的算术公式。
  • 请求改进工作代码的帮助更适合Code Review SE
  • 迭代地做。代码肯定会更简单。我猜 4-5 行代码,大约是你代码行数的一半,不包括 printfs。滥用递归从来都不是一个好主意
  • 叹息。看,伙计们,基本上每个要求递归解决方案的问题都是学生练习。告诉他们不递归就这样做违反了练习的条款。当体育教练告诉学生运动员多次在举重机上举重时,您不会告诉他们效率低下,他们应该使用叉车或水平仪。他们需要举重来锻炼肌肉,学生需要通过编写在锻炼之外毫无意义的代码来锻炼和锻炼大脑。
  • 这不是简单的等差数列吗?从 1-N,同时跳过小于 range_start 的那些?或者换句话说,从 1 到 N 的偶数和减去从 1 到 range_start 的偶数和?

标签: c recursion


【解决方案1】:

嗯,有一个数学公式可以计算这个,但如果你真的需要递归,你可以试试:

int sum_evens(int range_start, int range_end)
{
    if (range_start > range_end) return 0;
    int tmp = (is_even(range_start) == 0) ? range_start : 0;
    return tmp + sum_evens(range_start + 1, range_end);
}

但请注意,这样的递归函数是“危险的”。像sum_evens(0, 2000000000) 这样调用它很可能会产生堆栈溢出。

因此,如果您不想使用数学公式,更好的方法是使用简单的循环。

int sum_evens(int range_start, int range_end) {
    int sum = 0;
    if (is_even(range_start) != 0) ++range_start; // Make range_start even
    while(range_start <= range_end) 
    {
        sum += range_start;
        range_start += 2;
    }
    return sum;
}

顺便说一句:

当数字为偶数时,您的函数is_even 显然返回 0。这是相当不寻常的,因为值 0 通常意味着错误。但是,在上面我保持了相同的风格。

【讨论】:

  • sum_evensX 在返回线上?可能是错字?
  • @Shark 谢谢...测试时使用的名称,我错误地只更改了一次
【解决方案2】:

我知道您想递归地执行此操作,但就像 cmets 所说的那样,如果您正在寻找更好更快的解决方案,您可以使用简单的迭代或实际的算术公式,也就是说

#include <stdio.h>

int sum_evens(int range_start, int range_end) {
    printf("Entering sum function for range %d to %d\n",
           range_start, range_end);

    if (range_start > range_end) return 0;
    int val = range_start % 2 == 0 ? range_start : 0;
    return val + sum_evens(range_start + 1, range_end);
}

int main() {
    int val = sum_evens(1, 10);
    printf("\n%d", val);
    return 0;
}

这里不使用 if else 语句将值加到总和中,可以使用三元运算符,然后再次调用该函数以启动递归

如果你想使用 void 函数和指针

#include <stdio.h>

void sum_evens(int range_start, int range_end, int * initiator) {

    printf("Entering sum function for range %d to %d\n", range_start, range_end);

    if (range_start <= range_end) {
        int val = range_start % 2 == 0 ? range_start : 0;
        (*initiator) += val;
        sum_evens(range_start + 1, range_end, initiator);
    }
}

int main() {
    int sum = 0;
    sum_evens(1, 3, &sum);
    printf("\n%d", sum);
    return 0;
}

使用迭代(for循环)

#include <stdio.h>

int sum_evens(int range_start, int range_end) {
    int sum = 0;
    for (int i = range_start; i <= range_end; i++) 
        if (i % 2 == 0) sum += i;
    return sum;
}

int main() {
    int val = sum_evens(1, 10);
    printf("\n%d", val);
    return 0;
}

【讨论】:

  • @4386427 已编辑感谢您的反馈^_^ 我也看到你在我之前写了答案哈哈,留下一个赞成
  • 嗯,4 分钟是发布“相同”解决方案的可接受时间,所以不用担心。
  • 你有一个很棒的:D
【解决方案3】:

没有什么要补充的,但我有一个习惯,首先编写基本条件,以减少执行时间和它将分配的空间,因为在这里你的函数也上升到 n+1,这是不必要的。

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 2014-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
相关资源
最近更新 更多