使用递归和无循环查找数组中最长的升序子系列的长度

时间:2013-12-01 16:31:11

标签: c arrays recursion series

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

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);
    }
}

2 个答案:

答案 0 :(得分:2)

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

完整性检查

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

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

允许值

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

递归

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

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

  • 可以通过跳过当前处理的号码来访问最长的子系列
  • 可以通过添加当前处理的数字
  • 来访问最长的子系列
  • 当前处理的号码不适合

如果数字大于先前添加的最大数字,则可以添加数字;毕竟我们正在寻找一个提升系列。当前的数字可能比阵列中其他必须处理的数字要大。所以我们必须考虑两种可能性:没有它和它的连续递归步骤 - 只要它符合标准。

可能的疏忽

考虑到INT_MIN(机器上可能的最小int值)是数组中完全有效的数字。我添加了变量 see ,它只记录是否在数组中至少看过INT_MIN一次。在第一次遇到时,看到从0翻转到1,由于升序子系列的要求,不允许任何进一步的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);
}

答案 1 :(得分:1)

#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;    
}