递归算法时间复杂度

时间:2016-10-20 12:15:54

标签: algorithm time-complexity

我正在尝试两个找到合并 n 文件数量的递归函数的时间复杂度。

我的解决方案是 T(n)= kc + T(n-(k + 1))其中 n > 0, T(n)= T(0)其中 n = 0。

这是正确的还是有其他方法可以找到时间复杂度?

这是伪代码,

//GLOBAL VARIABLES
int nRecords = 0...k; //assume there are k records
int numFiles = 0...n; //assume there are n files
String mainArray[0...nRecords]; //main array that stores the file records

void mergeFiles(numFiles) { //params numFiles
  fstream file; //file variable
  if (numFiles == 0) {
    ofstream outfile; //file output variable
    outfile.open(directory / mergedfile); // point variable to directory
    for (int i = 0; i < sizeOf(mainArray); i++) {
      oufile << mainArray[i]; // write content of mainArray to outfile
    }
    outfile.close(); //close once operation is done
  } else {
    int i = 0; //file index counter
    file.open(directory / nextfile); //open file to be read

    if (file.isOpen()) {
      while (!file.eof() && i < sizeOf(mainArray)) {
        file >> mainArray[i]; //copy contents of file to mainArray
        i++; //increase array index
      }
    }
    file.close(); //close once operation is done
    mergeFiles(numFiles - 1); //recurse function
  }
}

int main() {
  mergeFiles(numFiles); //call mergeFile function to main
}

2 个答案:

答案 0 :(得分:1)

Going by your formula.

T(n)= kc+T(n-(k+1)) = kc+kc+T(n-(k+1)-(k+1)) = kc+kc+...+T(0) = ... 
    = kc*(n/(k+1)) ~ nc = O(n).

答案 1 :(得分:1)

k 的定义在您的问题中有点含糊不清,因为您为 T(n)提供的公式似乎假设您处理 k 记录每个文件,而代码中mainArray的定义表明 k 代表记录数,而不是单个文件中的记录数。

我首先假设 k 的第二个定义是正确的,所以你有:

  • n =文件数
  • k =这些文件中的记录总数=数组大小

读/写操作的时间复杂度

我认为你假设以下两个语句 - 读/写一条记录 - 在每个恒定时间运行:

file >> mainArray[i]; 

outfile << mainArray[i];    

请注意,此类操作所需的时间通常取决于记录的大小。但是由于你没有提供这个大小作为考虑因素,我将假设记录具有恒定的大小,因此可以认为这些操作在 O(1)中运行,即恒定时间。

关于递归

虽然您使用递归,但它确实关注tail-recursion,因此时间复杂度与迭代算法没有任何不同。无论哪种方式,else块都会执行 n 次。

事实上,使用递归公式计算时间复杂度并不是那么简单,因为您不知道一个文件中有多少条记录,只知道所有文件中的记录。您可以解决这个问题,并且人为地假设每个文件中都有 k / n 记录,但我发现根据else的绝对次数执行测量更加直观执行块,而不需要在递归公式中表达它。

测量

内部while循环的主体最多可以执行 k 次,并且假设您认为文件中有多少条记录,它将完全执行总计 k 次。

最后一部分(其中numfiles == 0)有一个for循环,也会执行 k 次。

因此决定时间复杂性的因素是:

  • 打开/关闭文件的固定时间,乘以 n
  • 读取/写入记录的恒定时间,乘以 k

所以时间复杂度是 O(n + k)

如果 k 的定义不同

如果 k 应表示一个文件中的记录数,那么您的代码是错误的,因为数组的大小必须 nk < / em>,而不是 k 。假设您仍然打算这样做,那么通过类似的推理,时间复杂度为 O(n.k)

关于程序正确性的注意事项

在实际情况中,您必须确保数组的大小与文件中的记录总数相对应,而不仅仅是假设是这种情况。如果阵列变小,则无法存储某些记录;另一方面,如果数组更大,则将数组转储到输出文件中的代码将包含从未初始化的数组元素。

因此,您最好使用具有动态大小(堆栈)的数组,因此其大小与实际读入的数据完全对应。