递归算法从列表中选择递增的非连续数字

时间:2011-12-25 22:09:22

标签: c recursion

我需要编写一个函数,在一个数字列表中找到最长的,不一定是连续的,升序的子序列。该函数需要递归。

我的算法有问题,我无法弄清楚如何修复它。这是一个示例起始列表:

  

[88,1,22,3,34,6,54,9,19]

正确的结果是:

  

[1,3,6,9,19]

我想在屏幕上打印这个子序列的长度,在本例中为5。

我的功能:

int subseires(int arraysub[], int small, int i, int j, int coun){
    if( i==size ) return 0;

    if( arraysub[i]>arraysub[j] )
        subseires(arraysub, small, i+1, j+1, coun);

    if( arraysub[i]<arraysub[j] )
        subseires(arraysub, small, i, j+1, coun+1);

    return coun;
}

任何人都可以通过我的程序指出问题来帮助吗?

3 个答案:

答案 0 :(得分:3)

你的算法可能是错误的。

你需要做的是对于aray的每个成员 - 如果你可以选择它(它不小于你选择的前一个)然后递归检查两个选项:选择它还是不选择它。这样你就可以直到数组的末尾并返回总长度。最后打印最长的长度。

尝试在C函数中实现此算法。

答案 1 :(得分:2)

所以你只需要打印列表的长度,而不是列表本身?这有帮助,因为它简化了内存管理(这是c的问题)。

这真的只是一个美化的搜索。在每一点你需要知道(1)当前值(如果有的话); (2)当前长度(如有); (3)清单中的位置; (4)已知的最大长度。使用零长度有助于跟踪何时没有当前值(因此您不需要“魔术”初始值)。返回值应该是最大长度。

在每次递归时,您可以跳过当前数字或将其包含在列表中(但前提是它小于当前值)。

所以代码只是:

#include <stdio.h>

int max(int a, int b) {
  return a > b ? a : b;
}

int find(int* data, int total_length, int offset, int previous,
         int run_length, int max_length) {
  // update max length if it has improved                                       
  if (run_length > max_length) max_length = run_length;
  // if we are at the end, return max                                           
  if (offset == total_length) return max_length;
  // if the current value is too small, we cannot include it                    
  if (run_length && data[offset] <= previous)
    return find(data, total_length, offset+1, previous, run_length, max_length);
  // otherwise, we want the best of either including it or not                  
  return max(
    // try including it                                                         
    find(data, total_length, offset+1, data[offset], run_length+1, max_length),
    // try excluding it                                                          
    find(data, total_length, offset+1, previous, run_length, max_length));
}

// test                                                                         
int main(int argc, char *argv) {
  int data[] = { 88, 1, 22, 3, 34, 6, 54, 9, 19 };

  printf("%d\n", find(data, 9, 0, 0, 0, 0));
  return 0;
}

显然这是一个糟糕的c代码(不是因为我没有使用数组初始化,有人“善意”修复(虽然他们没有费心去投票这个答案 - 我猜他们认为我有动力通过学习发布在这里从他们对C语法的深入了解),但因为它使用调用堆栈,使用单独的内存结构会更有效。)

(另外,我不得不说,写这样的东西作为一个递归函数比在循环中做更容易,因为你只记下你想要发生的事情 - 如果你有一个循环然后你需要担心改变价值观并重置它们以及所有那些混乱。问题是它滥用堆栈可怕。)

答案 2 :(得分:0)

您需要的递归函数将如下所示

void dfs (int curr, int length){
    if (length > max )max = length;
    if (curr >= index)
        return ;
    for (int I=curr+1;I <= index; I++){
        if (array[I] >= array[curr]){
            dfs (I, length+1);
        }
    }
}

这里array []是整数数组。数字用索引1填充到索引n。 'curr'是当前索引,'length'是具有递增数字的最大子序列的长度。 'max'是最大长度。要计算你应该调用的长度

dfs(0, 0);

对于完整的Java代码:http://pastebin.com/H315si0K