【发布时间】:2020-12-08 22:25:20
【问题描述】:
尝试分析以下算法的运行时复杂度:
问题:我们有一个 m * n 数组 A 由小写字母和目标字符串 s 组成。目的是检查目标字符串是否出现在A中。
算法:
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(A[i][j] is equal to the starting character in s) search(i, j, s)
}
}
boolean search(int i, int j, target s){
if(the current position relative to s is the length of s) then we find the target
looping through the four possible directions starting from i, j: {p,q} = {i+1, j} or {i-1, j} or {i, j+1} or {i, j-1}, if the coordinate is never visited before
search(p, q, target s)
}
我读到的一个运行时复杂性分析如下:
在数组A 中的每个位置,我们首先看到4 可能的探索方向。第一轮结束后,我们只有 3 个可能的选择,因为我们再也回不去了。所以最差的运行时复杂度是O(m * n * 3**len(s))
但是,我不同意这种分析,因为即使我们每轮只看到 3 个可能的选择,我们确实需要花费一次操作来检查该方向是否曾经被访问过。例如,在 java 中,您可能只使用一个布尔数组来跟踪一个地点是否曾被访问过,因此为了知道一个地点是否已被访问过,需要进行条件检查,这需要一次操作。我提到的分析似乎没有考虑到这一点。
运行时复杂度应该是多少?
更新:
假设目标字符串的长度为l,矩阵中给定位置的运行时复杂度为T(l)。然后我们有:
T(l) = 4 T(l- 1) + 4 = 4(3T(l - 2) + 4) + 4 = 4(3( 3T(l -3) + 4) + 4)) + 4 = 4 * 3 ** (l - 1) + 4 + 4 *4 + 4 * 3 * 4 + ...
+4 来自这样一个事实,即我们在每一轮中循环四个方向,除了递归调用自身 3 次。
【问题讨论】: