这个代码O(R*C)的最坏情况是什么
How is the worst time case for this code O(R*C)?
我在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
编写整数数组只适用于所有字节相同的某些整数,这对整数布局做出了不可移植的假设。最后,如果R或C超过神奇值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)
- 将树节点添加到向量向量中的 n 元树遍历的平均和最坏情况时间复杂度是多少?
- C++ - 最坏情况和平均情况插入时间复杂度在 std::unordered_map <int,int>?
- 有没有一种惯用的方法可以在不存储变换或不必要地重新计算的情况下找到数组变换的最小/最大值?
- 在不进行排序的情况下查找数组中n个最小值的索引
- 在最坏的情况下试验快速排序.它运行良好,但在最坏的情况下发生未知错误.我想
- std::regex 是否保证了最坏情况下的时间复杂度?
- 在没有额外代码的情况下链接两个独立类的最通用方法是什么?
- 使用c 中的sort()函数对字符串进行排序的最坏情况是什么是什么
- 快速排序实现的最坏情况提示
- while(true)可能发生的最坏情况是什么?
- 此算法的最坏情况运行时间是多少
- 快速排序-最坏的情况会导致堆栈溢出
- 这个代码O(R*C)的最坏情况是什么
- 在最坏的情况下,多少QPI延迟可以减慢任意应用程序的速度
- 在实时应用程序中最坏情况下执行的最快c++映射
- 为什么在最坏的情况下unorder_set重哈希复杂度可能是O(n^2)
- 对于unordered_map,最坏的情况是什么?
- 为什么c++程序要为局部变量分配比在最坏情况下需要的更多的内存?
- 如何对三个快速排序的中值进行最坏情况排列
- 最坏情况是Unordered_set插入