这个代码O(R*C)的最坏情况是什么

How is the worst time case for this code O(R*C)?

本文关键字:最坏 情况 是什么 代码      更新时间:2023-10-16

我在InterviewBit:上遇到了这个问题

int memo[101][101];
int findMinPath(vector<vector<int> > V, int r, int c) {
  int R = V.size();
  int C = V[0].size();
  if (r >= R || c >= C) return 100000000; // Infinity
  if (r == R - 1 && c == C - 1) return 0;
  if (memo[r][c] != -1) return memo[r][c];
  memo[r][c] =  V[r][c] + min(findMinPath(V, r + 1, c), findMinPath(V, r, c + 1));
  return memo[r][c];
}
Callsite : 
memset(memo, -1, sizeof(memo));
findMinPath(V, 0, 0);

假设R = V.size()C = V[0].size()以及V具有正元素

代码难道不会创建一个二进制树类型的函数调用,它接受O(2(m+n)),因为每个函数调用都会进行另外两个函数调用吗?

此算法使用了一种称为动态编程的技术。其本质是在查找表中记住中间结果,并将整体解决方案作为部分解决方案的组合。

在这种特殊情况下,您可以看到findMinPath的每个调用要么是具有恒定复杂性的叶调用(不是递归),要么使memo中的至少一个条目变为非负。很容易看出,如果memo中的所有条目都是非负的,那么函数将永远不会递归。由于只有R×memo中的C元素,这是整体复杂性的上界。

也就是说,实施起来相当笨拙。为什么要为memo使用全局变量,并依赖于调用方将其初始化为-1?此外,使用memset编写整数数组只适用于所有字节相同的某些整数,这对整数布局做出了不可移植的假设。最后,如果RC超过神奇值101,则存在缓冲区溢出漏洞。因此,如果你想变得迂腐,那么实际的复杂性是恒定的。

注意,对于给定的(r,c)

以下代码不会执行多次:

memo[r][c]=V[r][c]+min(findMinPath(V,r+1,c),findMinPath(V,r,c+1))

一旦备忘录[r][c]被设置,功能将在返回

if(memo[r][c]!=-1)返回memo[r][c]

因此,每个函数最多调用一次其他函数。换句话说,每个函数最终都会执行atmost O(1)次(请注意,您可以在调用站点转移有关检查memo[r][c]!=-1的部分)。

对于(R,C),O(R*C)可能的组合数目是可能的因此,函数的时间复杂度:O(R*C)

此代码最糟糕的时间复杂度是O(R*C),因为我们使用自上而下的动态编程方法,将值存储在memo[r][c]中,因此递归调用只发生一次,第二次它将执行以下行

具有O(1)复杂度的CCD_ 12。

可能的总组合为R*C,因此其时间复杂性将为O(R*C)