【问题标题】:How is the recursion in the following question works?以下问题中的递归如何工作?
【发布时间】:2020-11-07 07:15:27
【问题描述】:

我有一个测试问题和解决方案。

问题是:编写一个函数,如果我们可以将一个数组分成两个不同的组,它们的总和相等,则返回 1,否则返回 0。 例如:数组:[1,4,0​​,3] 可以分为两组,它们的和相等,因此:1+3=0+4

建议的解决方案如下:

#include<stdio.h>

int can_split(int arr[], int n, int sum1, int sum2); // Function Signature

int can_split(int arr[], int n, int sum1, int sum2)
{
    if (n == 0)
        return sum1 == sum2;
    return can_split(arr + 1, n - 1, sum1 + arr[0], sum2) || can_split(arr + 1, n - 1, sum1, sum2 + arr[0]);
}

int main()
{
    int sum1_main = 0, sum2_main = 0;
    int arr_main[] = { 1,2,4 };
    printf("Function returned: %d", can_split(arr_main, 4, sum1_main, sum2_main));
    return 0;
}

我不明白的是这条线的想法:

return can_split(arr + 1, n - 1, sum1 + arr[0], sum2) || can_split(arr + 1, n - 1, sum1, sum2 + arr[0]);

当涉及到复杂的问题时,递归对我来说是一个非常困难的话题。

如果有人能解释这行是如何工作的以及老师为什么要写 || 将非常感激? 我知道它的意思是“或”,但它到底是做什么的呢?

【问题讨论】:

  • 当第一部分为真时,返回真,第二部分不执行。否则返回第二部分的返回值。
  • 在递归的第一级,该算法将数组的第一个元素分派到第一个或第二个子集,分别为 sum1 和 sum2:|| 的左侧和右侧。在递归的第二级,它对数组的第二个元素执行相同的操作,依此类推。它最终遍历一个二叉树,在子集 1 或子集 2 中分派元素,当它找到 sum1 = sum2 的叶子时结束搜索
  • main中的can_split(arr_main, 4, sum1_main, sum2_main))不应该是can_split(arr_main, 3, sum1_main, sum2_main)),以int arr_main[] = { 1,2,4 };的数组为参数n是元素的数量吗? --- 最好使用can_split(arr_main, sizeof(arr_main) / sizeof(*arr_main), sum1_main, sum2_main))。

标签: arrays c xcode recursion numbers


【解决方案1】:

当涉及到复杂时,递归对我来说是一个非常困难的话题 问题。

递归并不是一个很难的话题,而是一种思考和查看代码的方式(不仅仅是代码)。这主要是一个习惯和实践的问题,你越会阅读、写作和思考递归,它对你来说就越自然。
我要补充一点,恕我直言,在软件开发或计算机科学方面,这是一个不可避免且必要的概念。

关于这一行:

return can_split(arr + 1, n - 1, sum1 + arr[0], sum2) || can_split(arr + 1, n - 1, sum1, sum2 + arr[0]);

变量的含义如下:

  • arr 表示我们正在考虑的数组的当前元素的地址。在递归调用的每一步,我们都会考虑下一个元素(因此arr + 1 指向数组中的下一个元素)
  • n 表示要考虑的元素数量:我们以 n = 4 开始对函数的第一次调用,它表示数组的长度。我们使用n 作为停止条件。当n == 0 时,我们知道所有的元素都已经考虑过了。
  • sum1 和 sum2 代表当前求和值

现在,线的含义如下:
"当且仅当
-> 可以将数组拆分为与第一组中的当前元素相等的两组
或(因此||)
-> 可以将数组拆分为与第二组中的当前元素相等的两组。”

我们对每个元素都这样做,这保证了我们最终会得到正确的结果。

通常,理解代码的一个好方法是在一个小示例上手动运行它(这里 arr_main 将是 {1, 3, 0, 4})。
下面是它的开始方式:

can_split(arr_main, 4, 0, 0)  // no element has been affected to any sum
n == 0 ? no so we continue
return can_split(arr + 1, 3, 1, 0)   // the value 1 is affected to sum1
             || 
       can_split(arr + 1, 3, 0, 1);  // the value 1 is affected to sum2  

一直如此,直到所有值都受到影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-26
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    相关资源
    最近更新 更多