使用递归查找具有相等数字0和1的最大子阵列的长度

时间:2018-04-05 13:38:05

标签: c arrays algorithm function recursion

给定一个只有0's1's的数组,找到具有相同数量0's1's的最大子数组的长度。例如,给定一个数组

011110001

具有相同数量的0's1's的最大子数组的长度为8,从索引0到索引7。

撰写递归函数largestSubarray。这个函数有3个输入:一个数组--A,它的第一个元素的索引 - start,它的最后一个元素的索引 - 结束,并返回largestSubarray的大小。如果找不到具有相同数量的0's and 1's的子数组,则该函数应返回0.

int largestSubarray(int * A, int start, int end){
  int i, j=0, k=0;
  for(i=start; i<=end; i++){
    if(arr[i]==0){
     j++;
    }
    else if(arr[i]==1){
     k++;
    }
    if (j==k){
return (end+1-start)+largestSubarray(array, start+1, end);
    }

   }

如何修复此代码?请帮忙。感谢。

2 个答案:

答案 0 :(得分:1)

目前还不清楚你是否解决了这个问题。递归可以为那些特别适合的任务提供优雅的解决方案,或者无法合理编写程序解决方案。每个递归调用都是一个单独的函数调用,需要一个完整的独立函数堆栈。随着递归次数的增加,这会迅速耗尽并耗尽可用内存。应该首选程序解决方案。

此外,您的数组011110001必须是包含值

的数组的简写
0, 1, 1, 1, 1, 0, 0, 0, 1

自己,011110001,是2396161八进制常量

在这里,找到零和一个最大的平衡子阵列可以通过循环轻松完成。但是,理解它是一个练习题考试,它具有教育价值。

一个干净的解决方案是编写一个largestsubarray包装函数来调用第二个递归函数,传递size的整数指针作为内部调用的额外参数。通过提供单个地址保持大小,可以消除在递归展开时覆盖值的可能性。

在单个函数中,关键是强制每个递归调用返回,否则在递归函数展开时会遇到覆盖size的问题。一种实现可能是:

/* end must be ending index -- not size */
int largestsubarry (int *a, int start, int end)
{
    int o = 0, z = 0;       /* ones, zeros */

    if (end <= start)
        return 0;

    /* count the ones and zeros in subarray */
    for (register int i = start; i <= end; i++) {
        if (a[i] == 1)
            o++;
        else if (a[i] == 0)
            z++;
        else
            o = z = 0;      /* reset on any other value */
    }

    if (o != z) {   /* ones & zeros not equal */
        int s = largestsubarry (a, start + 1, end), /* test eliminating */
            e = largestsubarry (a, start, end - 1); /* each end */

        if (s > e)  /* return largest */
            return s;
        else
            return e;
    }
    else    /* balanced sub-array found, return size */
        return o + z;
}

注意:虽然不是错误,但C的标准编码样式避免使用camelCaseMixedCase变量名来支持所有 lower- case 同时保留大写名称以供宏和常量使用。这是一个风格问题 - 所以它完全取决于你,但没有遵循它可以导致某些圈子里的第一印象错误。)

示例使用/输出

传递包含以下值的整数数组会导致定位连续零和1的最大平衡子数组的正确大小,例如

$ ./bin/subarray
enter array (ctrl+d ends): 0 1 1 1 1 0 0 0 1
size: 8

$ ./bin/subarray
enter array (ctrl+d ends): 1 1 0 1 1 1 1 0 0 0 1
size: 8

$ ./bin/subarray
enter array (ctrl+d ends): 1 1 0 1 1 1 1 0 0 0 1 0
size: 10

$ ./bin/subarray
enter array (ctrl+d ends): 1 1 0 1 0 0 0 0 0 0 1
size: 6

$ ./bin/subarray
enter array (ctrl+d ends): 0 2 2 2 2 0 0 0 2
size: 0

可能有更有效的方法,但关键是知道要消除哪一端以找到最长的平衡子阵列。

答案 1 :(得分:0)

由于这显然是一个编码挑战,我只是提供一种方法来解决它。

  1. 计算1的数量和0的数量。如果它们匹配,则返回数组的长度:end+1-start,因为这是最长的平衡子数组。
  2. largestSubarray(array, start+1, end)largestSubarray(array, start, end-1)递归致电,并返回最高的数字。
  3. 可能有更有效的方法来解决它,但这是挑战的一部分!

    修改

    一个简单的改进是在计算1&0和0之前检查数组的长度。如果长度是奇数,则没有计算它们的点数(假设它们是数组中唯一可能的值),因此如果长度为奇数,您可以直接跳到第2步。