我试图总结给定数组中的数字,使用 recursion ,尝试了这段代码,但它不起作用。为啥?

Posted

技术标签:

【中文标题】我试图总结给定数组中的数字,使用 recursion ,尝试了这段代码,但它不起作用。为啥?【英文标题】:I'm trying to sum up the numbers in a given array, using recursion , tried this code but it isn't working. Why?我试图总结给定数组中的数字,使用 recursion ,尝试了这段代码,但它不起作用。为什么? 【发布时间】:2022-01-18 19:53:54 【问题描述】:
#include <iostream>

   using namespace std;

   int sumByRecursion( int arr[]) 
        int sum = 0;
        int n = sizeof(arr)/sizeof(arr[0]);
        //n is the size of the array
        if (n == 0) 
            return sum;
         else 
            n -= 1;
            for (int i=0;i=n;++i)
                arr[i]=arr[i+1];
            
            return (sum + arr[0] + sumByRecursion( arr));
        
    

   int main() 
        int arr[]=2, 4, 6;
        sumByRecursion( arr);

        return 0;
    
    

sumByRecursion 基于这个想法工作: 1-如果数组的大小为0“空数组”,则返回总和。 2-如果大小不为0“数组不为空”,对sum的第一个元素求和,然后调用函数,将数组的大小减1,对新数组进行sumByRecursion。

【问题讨论】:

int n = sizeof(arr)/sizeof(arr[0]); 无法按您希望的方式工作。在函数内部,参数arr 已衰减为类型int*,并且对数组中的元素数量一无所知。 看来您正在使用int n = sizeof(arr)/sizeof(arr[0]); 来确定数组的大小。这不计算数组的大小。可能是一个错误。 int arr[]=2, 4, 6; --> std::array&lt;int, 3&gt; arr = 2,4,6; 然后使用 arr.size() 而不是您现在使用的来确定元素的数量(如上所述,这是错误的)。 对于应该是简单循环的代码是否需要使用递归?如果是这样,你有我的同情。无论如何,不​​要删除第一个元素,只需指向下一个元素。删除for 循环,对于递归调用,使用sumByRecursion(arr + 1)。而且,正如其他 cmets 所指出的,您应该将数组的大小作为参数传递。 另外请注意,您使用的不是函数提供的结果。 【参考方案1】:

您需要将数组的大小传递给sumByRecursion 例程。

之所以需要传递数组的大小,是因为数组不跟踪自己的大小。

std::arraystd::vector 等替代方法提供了查询它们的大小的功能,但 C 样式的数组不携带该信息。

std::size 函数查询 type(在该上下文中是 C 风格的数组)以计算大小。一旦作为int arr[] 参数传递,arr 类型就是int*,它不再能够产生大小信息。

int arr[] 参数是int* arr 的一种写法,但建议读者arr 参数是一个C 风格的数组。可以被认为是自记录代码,如果正确完成 - 但许多程序会将参数表示为 int* arr 所以,唉,它不是一个普遍的习惯用法。

#include <cstddef>
#include <iterator>
#include <iostream>

using std::cout;
using std::size;
using std::size_t;

namespace 

int sumByRecursion(int arr[], size_t n) 
    if (n == 0) 
        return 0;
     else 
        // Many C++ compilers do not perform tail recursion optimization.
        // But for those that do, this will thwart tail recursion optimization.
        return arr[0] + sumByRecursion(arr+1, n-1);
    


 // anon

int main() 
    int arr[] = 2, 4, 6;
    auto arr_size = size(arr);
    auto sum = sumByRecursion(arr, arr_size);
    cout << sum << "\n";

【讨论】:

真的我觉得你应该提一下你需要传递尺寸的乳清。【参考方案2】:

一个(可悲的)常见错误:

int sumByRecursion( int arr[] )
 // What do you think  ^^^^^  this is?

    int n = sizeof(arr)/sizeof(arr[0]);
    //      ^^^^^^^^^^^ Sorry, too late.
    // ...

正如评论部分已经指出的那样

在函数内部,参数arr 已衰减为 int* 类型,并且对数组中元素的数量一无所知。 (Richard Critten)

简而言之:int sumByRecursion( int arr[])int sumByRecursion( int *arr) 完全相同。参数列表中的[] 语法只不过是语法糖。 (PaulMcKenzie)

解决方案是将大小与指针一起传递,或者显式地作为单独的函数参数传递,或者在 std::spanstd::ranges::range 等对象内部传递。

当然,另一种方法是传递 std::cbegin() 和 std::cend() 返回的两个迭代器。


用于“将数组的大小减少1”的代码可能是同样的误解:

int sum = 0;
// ...
if (n == 0)               // Ok...
    return sum;
 else 
    n -= 1;                // Okayish...
   
    for (int i=0;i=n;++i) // 
        arr[i]=arr[i+1];   // <-- There's NO need to do all those copies!
                          // 

    return (sum + arr[0] + sumByRecursion( arr));
    //                                    ^^^^ This does NOT pass an array


Eljay 的answer 展示了如何正确实现 OP 的算法。

只是为了好玩(1),一个堆栈友好的实现

#include <iostream>

int sumByRecursion(size_t n, int const* arr)

    // Stop the bloody recursion
    if ( n == 0 )
        return 0;
    if ( n == 1 )
        return arr[0];
    
    // Divide et impera
    size_t middle = n / 2;
    return sumByRecursion(middle, arr)
         + sumByRecursion(n - middle, arr + middle);


int main()

    int arr[] 2, 4, 6;

    std::cout << sumByRecursion(std::size(arr), arr) << '\n';

(1) 说真的,不要使用这个。这是完全低效和无用的复杂。请改用正确的algorithm。

【讨论】:

【参考方案3】:

我可以使用算法深度优先搜索为您的问题提供解决方案。

#include <iostream>
#include <vector>
using namespace std;
const int maximumSize=10;
vector<int> visited(maximumSize, 0);
int dfs(int current, int previous, vector<int>& input)

    if(visited[current]==1)
    
        return 0;
    
    visited[current]=1;
    int summarize=0;
    for(int next=(current+1); next<input.size(); ++next)
    
        if(next==previous)
        
            continue;
        
        summarize+=dfs(next, current, input);
    
    summarize+=input[current];
    return summarize;

void solve()

    vector<int> inputVector=2, 4, 6;
    cout<<dfs(0, -1, inputVector);
    return;

int main()

    solve();
    return 0;

结果如下:

12

【讨论】:

以上是关于我试图总结给定数组中的数字,使用 recursion ,尝试了这段代码,但它不起作用。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

数组中的两个不同数字,它们的和等于给定值

汇编代码返回数组中的最小整数,而不是随机返回最后一个或倒数第二个数字

不使用数组或循环找到五个给定数字中第三大的最快方法?

快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值

来自给定数组的查询中的 Laravel 多个 where 子句

如何计算 json 对象数组中的值? (在 VueJS 中)