如何降低此问题中的时间复杂度

How to reduce time complexity in this problem

本文关键字:时间复杂度 问题 何降低      更新时间:2023-10-16

我最近在一次采访中被问到这个问题,我想知道如何回答这个问题。

您有一个任意随机顺序
的二进制数字 2D 矩阵0 0 0 0 0 0 0 0
1 0 0 1 1 1 1 01 0 0 0 1 1 1 1

1 0 1 1 0 1 1 0
1 1 0 0 0 0 1 1
1 0 1 0 1 1 0 0

你需要找到这种模式
的发生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);
}

下一个问题是获得更好的时间复杂度。 我无法回答确切的解决方案

有人可以帮助我吗?我只是出于自己的好奇心想知道这一点。

这是一个取决于输入模式的小优化。

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);
}

操作的时间复杂度可以描述为 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) 次。

至于具体问题,你的解决方案是合适的。

如果您想在同一矩阵中找到其他模式,或者非常大的矩阵和更大的模式,有 2 种替代方法会有所帮助:

https://en.wikipedia.org/wiki/Summed-area_table

https://en.wikipedia.org/wiki/Discrete_Fourier_transform

两者都需要对原始矩阵进行一些预处理,但随后会更快地检查模式模板。您可以在 OpenCV 图像处理库中找到两者的实现。