最大递增连续子数组(C ++)的递归长度

时间:2019-06-28 19:31:01

标签: c++ algorithm recursion

我在大学里有个作业,要用C ++编写一个递归函数,该函数可以找到数组或整数中最长的连续递增子数组的长度。另外,我有一个代码框架,必须将其用于我的代码,并且该函数不得包含循环和更多函数。

例如,对于数组1,2,4,6,4,21,21,22,0,1,3,5,100,7 结果将为5(因为0到100是5个数字)。

骨骼是:

#include <stdio.h>
#define MAX_SIZE 1000

int get_max_series(int a[], int size);

int main() {
    int i, size_array, array[MAX_SIZE];
    scanf("%d", &size_array);
    for (i = 0; i < size_array; i++)
        scanf("%d", &array[i]);
    printf("%d", get_max_series(array, size_array));
    return 0;
}

int get_max_series(int a[], int size) {
    // My code should be here
} 

我已经成功编写了一个计算递增对数的函数,但是当计数对下降时却无法重置计数器。代码如下:

#include <stdio.h>
#define MAX_SIZE 1000

int get_max_series(int a[], int size);

int main() {
    int i, size_array, array[MAX_SIZE];
    scanf("%d", &size_array);
    for (i = 0; i < size_array; i++)
        scanf("%d", &array[i]);
    printf("%d", get_max_series(array, size_array));
    return 0;
}

int get_max_series(int a[], int size) {
    if (size == 1)
        return 1;

    if (a[0] < a[1])
        return 1 + get_max_series(&a[1], size - 1);

    return get_max_series(&a[1], size - 1);
} 

我很乐意获得一些建议,以使我的代码在这种情况下可以正常工作,或者完全更改代码。 谢谢!

3 个答案:

答案 0 :(得分:2)

这是一个似乎遵循您的规则的O(n)例程(变量名称应有助于解释发生的情况):

#include <stdio.h>
#define MAX_SIZE 1000

int get_max_series(int a[], int size);

int main() {
    int i, size_array, array[MAX_SIZE];
    scanf("%d", &size_array);
    for (i = 0; i < size_array; i++)
        scanf("%d", &array[i]);
    printf("%d", get_max_series(array, size_array));
    return 0;
}

int get_max_series(int a[], int size) {
    int i = size - 1;

    if (i < 2){
      if (a[1] > a[0])
        return a[0] = 2;
      else
        return a[0] = 1;
    }

    int max = get_max_series(a, i);
    int max_up_to_i = a[i - 2];

    if (a[i] > a[i - 1]){
      a[i - 1] = 1 + max_up_to_i;
      if (a[i - 1] > max)
        max = a[i - 1];

    } else {
      a[i - 1] = 1;
    }

    return max;
}

答案 1 :(得分:1)

如果您不想使用静态/全局变量或辅助函数,则可以对大小大于1的数组使用以下缩减形式(尽管这样做很慢,因为它会进行两次递归调用):

如果a[0]>=a[1],则我们不能在最大升序子数组中包含a[0],因为它违反了我们的升序概念,因此我们像在代码中一样返回get_max_series(a + 1,size-1)。

a[0]<a[1]时,我们有两种情况:

如果get_max_series(a+1,size-1)==size-1,则整个子数组a [1],...,a [size-1]递增。这意味着a [0],a [1],...,a [size-1]也在上升,因此在这种情况下我们可以返回1 + get_max_series(&a[1], size-1)

如何,如果get_max_series(a+1,size-1)!=size-1表示子数组a [1],...,a [size-1]没有升序,则最大子数组不能同时包含两个[1]和a [size-1](由于连续性,它必须包括介于两者之间的所有内容,这会使它不升序)。

因此,您返回max(1+get_max_series(&a[0], size-1), get_max_series(&a[1], size-1))。 请注意,这里您对get_max_series进行了两次调用,因此您的计算成本会迅速增长(基本上与执行fibonacci函数的朴素递归实现时出现的效率低下相同)。

该功能类似于

int get_max_series(int a[], int size) {
    if (size <= 1)
        return size;
    int max_sub = get_max_series(&a[1], size - 1);
    if (a[0] >= a[1])
        return  max_sub;
        else{
            if (max_sub==(size-1))
                return size;
            else
                return std::max(get_max_series(&a[0], size-1), max_sub);
            }
}


我在这里使用std::max,但是如果您不想使用algorithm库,则可以使用if-else查找最多两个数字。

答案 2 :(得分:-1)

最长的升序子数组不一定从数组的开头开始。因此,

    return 1 + get_max_series(&a[1], size - 1);

不正确。我看不到如何仅依靠检查一个字符(至少在给定签名内)来挽救这种方法。考虑在数组的开头找到最长的升序,然后沿着以下行递归到其余序列:

    int get_max_series(int a[], int size)
    {
        int n = get_longest_acsending_prefix(a, size);
        if (n == size)
            return n;
        return max(n, get_longest_ascending_prefix(a + n, size - n));
    }

也就是说,我在这里看不到递归点。