如何降低这个问题的时间复杂度
Posted
技术标签:
【中文标题】如何降低这个问题的时间复杂度【英文标题】:How to reduce time complexity in this problem 【发布时间】:2019-04-27 10:51:20 【问题描述】:我最近在一次采访中被问到这个问题,我想知道如何回答这个问题。
你有一个任意随机顺序二进制数字的二维矩阵
0 0 0 0 0 0 0 0
1 0 0 1 1 1 1 0
1 0 0 0 1 1 1 1
1 0 1 1 0 1 1 0
1 1 0 0 0 0 1 1
@987654326 @并且你需要找到这种模式的出现
1
11
所以,看上面的矩阵很明显答案是6。 我就这样解决了
unsigned int Findpairs(const std::vector<std::vector<unsigned int>>& A)
unsigned int count = 0;
for (unsigned int i = 0; i < (A.size()-1); i++)
for (unsigned int j = 0; j < (A[i].size()-1); j++)
if(A[i][j]==1 && A[i+1][j]==1 && A[i+1][j+1]==1)
count++;
return (count);
下一个问题是获得更好的时间复杂度。 我无法回答确切的解决方案。
有人可以帮我解决这个问题吗?我只是出于自己的好奇心而想知道这一点。
【问题讨论】:
首先,问自己两个问题。一、yo9ur算法的时间复杂度是多少?其次,是什么驱动了它?如果你不能回答这些问题,你就无法知道是否可以改进时间复杂度,更不用说如何改进了。 对于这个解决方案,我的 T 复杂度为O(n^2)
2 个 for 循环将始终执行。我仍然找不到更好的解决方案。有没有
我认为面试官的意图是看你的思考过程。这个问题与在给定字符串(长度 n)中寻找子字符串(长度 m)非常相似,其朴素算法的复杂度为 O(n*m)
。在这种情况下,搜索空间是二维的,复杂度是 O(n^2 * m)
其中m
是要搜索的模式的长度(在您的情况下为 3)。或许,面试官希望你按照与 KMP 算法(以及类似的 O(n) 子字符串搜索算法)类似的思路在 2 维中思考。
【参考方案1】:
这是一个依赖于输入模式的小优化。
unsigned int Findpairs(const std::vector<std::vector<unsigned int>>& A)
unsigned int count = 0;
for (unsigned int i = 0; i < (A.size() - 1); i++)
for (unsigned int j = 0; j < (A[i].size() - 1); j++)
if (A[i + 1][j + 1] == 1)
if (A[i + 1][j] == 1 && A[i][j] == 1)
count++;
else
j++; //skip a column because our bottom right saw 0
return (count);
【讨论】:
好主意,额外的轻微改进可能是矩阵条目的 'unit8_t' 并检查 '!= 0' 而不是 '== 1' 嘿,这是个好主意,我想知道它是否不同于先检查A[i][j] == 1
,然后检查A[i + 1][j] == 1 && A[i + 1][j + 1] == 1
。我觉得不行!!!【参考方案2】:
操作的时间复杂度可以描述为 O(n),其中 n 是数组中的点数。您的操作相当于在未排序的数组中搜索某些内容。有一些方法可以让你的算法更高效,但你不能在少于线性时间 O(n) 内执行这种类型的搜索。
对于某些问题,您可以通过先排序或收集有关该问题的附加信息来提高时间复杂度。在这个问题的情况下,您可以证明您的解决方案与数组的大小线性相关。使用随机数组,这 3 个元素中的每一个都有 50% 的机会出现。对于每个 n,模式发生的几率是 0.5^3 = 1/8。这意味着您将计算大约 1/8*n 次出现的模式。 仅计算模式需要 O(n) 时间。
如果您的目标是估计随机数组中出现的次数,您可以在 O(1) 时间内给出估计值。这种模式应该在随机数组中出现大约 1/8*(j-1)*(i-1) 次。
【讨论】:
【参考方案3】:至于具体问题,你的解决方案是合适的。
如果您想在同一个矩阵中找到其他模式,或者在非常大的矩阵和更大的模式的情况下,有 2 种替代方法会很有用:
https://en.wikipedia.org/wiki/Summed-area_table
https://en.wikipedia.org/wiki/Discrete_Fourier_transform
两者都需要对原始矩阵进行一些预处理,但会为模式模板提供更快的检查。您可以在 OpenCV 图像处理库中找到两者的实现。
【讨论】:
以上是关于如何降低这个问题的时间复杂度的主要内容,如果未能解决你的问题,请参考以下文章