【问题标题】:Finding the length of the longest ascending sub-series in an array using recursion and no loops使用递归和无循环查找数组中最长的升序子系列的长度
【发布时间】:2013-12-17 08:12:30
【问题描述】:

我已经被困了好几个小时,试图弄清楚如何编写一个获取整数数组的函数,并使用递归和根本没有循环来找到数组中最长的升序子系列的长度。我只允许使用另外 1 个递归函数 例如,对于以下数组:{45,1,21,3,3,6,53,9,18},outpot 应该是 5,因为最长的子序列是 {1,3,6,9,18 }。 因此,基本上,一个函数获取一个数组及其大小,并且需要打印最长子系列的长度,根本不使用循环,没有全局/静态类型,它可能使用另一个“帮助”递归函数,就是这样它。 这几乎就是我想出的全部,而且它一团糟,而且效果不佳。 我正在尝试扫描数组,而我一直都知道我正在查看的当前索引、与当前进行比较的索引以及我开始当前子系列的原始索引。 我试图在知道应该比较的索引的同时扫描数组,但我被卡住了,这就是我得到的,我真的很感激任何提示和建议。 谢谢。

void max_set(int arr[], int size)
{
    int bigSeries[2] = { 0 };
    calcSeries(arr, bigSeries,0, 0, 1, size -1, 1);
    printf("number of max parts going up %d \n", bigSeries[0]);

}
 void calcSeries(int arr[], int bigSeries[],int originalCHeckedIndex, int checkedIndex,      int currentIndex, int lastIndex, int ascending)
{
    if ((checkedIndex == lastIndex) || (currentIndex > lastIndex))
    {
        if (ascending > bigSeries[0])
            bigSeries[0] = ascending;
        if (originalCHeckedIndex == lastIndex)
            return;
        else
        {
            calcSeries(arr, bigSeries, originalCHeckedIndex + 1, originalCHeckedIndex + 1, originalCHeckedIndex + 2, lastIndex, 0);
            return;
        }
    }
    if (arr[currentIndex] > arr[checkedIndex])
    {
        calcSeries(arr, bigSeries, originalCHeckedIndex, currentIndex, currentIndex + 1, lastIndex, ascending + 1);
    }
    else
    {
        if (arr[originalCHeckedIndex] < arr[currentIndex])
            calcSeries(arr, bigSeries, currentIndex, currentIndex, currentIndex + 1, lastIndex,ascending);
        calcSeries(arr, bigSeries, originalCHeckedIndex, checkedIndex, currentIndex + 1, lastIndex, ascending);
    }
}

【问题讨论】:

  • 尝试先用循环做,这样你就明白逻辑了...
  • 只需使用循环即可。 C 支持循环。

标签: c arrays recursion series


【解决方案1】:

该算法与第一个答案有许多相似之处,但涵盖了一些您可能需要注意的极端情况。我没有写冗长的评论,而是选择写一个新的答案。

健全性检查

对数组进行一些完整性检查,就像我在函数 max_set() 中所做的那样。

  • 是否提供了数组(检查是否为 NULL)?
  • 提供的数组大小是否至少为正(考虑 size_t)?

允许的值

数据类型int允许正负值。该算法应该同时处理这两个问题。至少我没有从你的帖子中读到他们必须是积极的。如果你跳过那部分,我的代码看起来会更好一些。

递归

这个算法的思想(和第一个答案的那个)是递归遍历数组,从第一个元素开始,最后结束。所以这已经定义了递归的开始和结束,如源代码中所述。

要以这种方式找到最长的数字子序列,总是有三种可能性:

  • 跳过当前正在处理的数字可以达到最长的子系列
  • 加上当前正在处理的数字,可以达到最长的子系列
  • 当前处理的号码不适合

如果一个数字大于之前添加的最大数字,则可以添加该数字;毕竟,我们在寻找一个上升的系列。当前数字可能大于数组中必须处理的其他数字。所以我们必须考虑这两种可能性:在没有它和有它的情况下继续递归步骤——只要它符合标准。

可能的疏忽

考虑到 INT_MIN,机器上可能的最小 int 值,是数组中完全有效的数字。我添加了变量 seen,它只记录 INT_MIN 在数组中是否至少出现过一次。在第一次遇到时,seen 从 0 翻转到 1,由于 ascending 子系列的要求,不允许任何进一步的 INT_MIN 值。您的示例显示了此要求,出现了两次数字 3。

测试

尝试寻找各种测试用例,并有时跳出框框思考。 NULL 表示数组,负大小,空数组。接下来,添加花哨的值,例如负数 INT_MIN。或者创建上升系列,下降系列,交错。多次出现的数字...

#include <sys/limits.h>

#include <stdio.h>

int
analyze(int arr[], int size, int min, int seen)
{
    int sub_count = 0, count = 0;

    /* end of recursion */
    if (size == 0)
        return 0;

    /* recursion step, without and with current number */
    sub_count = analyze(arr + 1, size - 1, min, seen);
    if (arr[0] > min || (min == INT_MIN && arr[0] == INT_MIN && !seen))
        count = 1 + analyze(arr + 1, size - 1, arr[0], arr[0] == INT_MIN);

    /* return length of largest sub-series */
    return sub_count > count ? sub_count : count;
}

void
max_set(int arr[], int size)
{
    int seq = 0;

    if (arr != NULL && size > 0) {
        /* start of recursion */
        seq = analyze(arr, size, INT_MIN, 0);
    }

    printf("max sequence is %d\n", seq);
}

int
main(void)
{
    int arr[] = { 45, 1, 21, 3, 3, 6, 53, 9, 18 };
    max_set(arr, sizeof(arr) / sizeof(*arr));
    return (0);
}

【讨论】:

  • 我不明白 INT_MIN 的概念,基本上该函数应该处理每个数字(正数或负数)。您的意思是我会使用 INT_MIN 作为“定义”值吗?因为我做不到……我不明白算法的主要思想……谢谢
【解决方案2】:
#include <stdio.h>

int calcSeries(int arr[], int size, int value, int count){
    int self, skip, rest;
    if(0 == size)
        return count;
    skip = calcSeries(arr + 1, size-1, value, count);//case of skip the top(self)
    if(value < *arr){
        self = calcSeries(arr + 1, size-1, *arr, count+1);//case of include top
        if(skip > self)
            self = skip;
    } else
        self = skip;
    rest = calcSeries(arr + 1, size-1, -1, 0);
    return self > rest ? self : rest;
}
void max_set(int arr[], int size){
    printf("number of max parts going up %d \n", calcSeries(arr, size, -1, 0));
}

int main(void){
    int array[]={45,1,21,3,3,6,53,9,18};
    max_set(array, sizeof(array)/sizeof(*array));
    return 0;    
}

【讨论】:

  • 你能解释一下'*arr'这行吗,我相信我也不应该使用指针...
  • @user3921 *arrarr[0]。有同样的意思。此外,传递给函数的数组意味着指针。
猜你喜欢
  • 2018-02-19
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
  • 2022-01-10
相关资源
最近更新 更多