【问题标题】:Recursive algorithm time complexity递归算法时间复杂度
【发布时间】:2017-01-17 19:47:11
【问题描述】:

我正在尝试两个找到合并 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
}

【问题讨论】:

    标签: algorithm time-complexity


    【解决方案1】:

    按照你的公式。

    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).
    

    【讨论】:

      【解决方案2】:

      k 的定义在您的问题中有点模棱两可,因为您为 T(n) 提供的公式似乎假设您处理 k em> 记录每个文件,而代码中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 应该表示 one 文件中的记录数,那么您的代码是错误的,因为数组的大小必须是 n.k,而不是 k。假设您仍然打算这样做,那么使用类似的推理时间复杂度是 O(n.k)

      关于程序正确性的说明

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

      因此,您最好使用具有动态大小(堆栈)的数组,因此它的大小与实际读入的记录数完全一致。

      【讨论】:

        猜你喜欢
        • 2011-02-12
        • 1970-01-01
        • 1970-01-01
        • 2017-07-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多