【问题标题】: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 维中思考。

标签: c++ algorithm time-complexity


【解决方案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 &amp;&amp; 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 图像处理库中找到两者的实现。

    【讨论】:

      猜你喜欢
      • 2020-01-16
      • 1970-01-01
      • 2022-06-28
      • 2012-07-28
      • 1970-01-01
      • 2011-06-15
      • 2016-01-08
      • 1970-01-01
      相关资源
      最近更新 更多