【问题标题】:time complexity for array search数组搜索的时间复杂度
【发布时间】:2017-09-17 20:15:11
【问题描述】:

我正在编写函数来检查给定值是否包含在 .该矩阵具有以下性质: • 每行中的整数从左到右升序排序。 •每列中的整数从上到下按升序排序

public static boolean searchMatrix(int target, int[][] matrix)
{
    for(int i = 0;i <= matrix[0].length;i++)
    {
        for (int j=i; j<matrix.length;j++)
        {
        if(target == matrix[i][j])
        return true;
        }
    }
    return false;
}

我想知道这个程序的时间复杂度为 O(N)。 如果不是,我应该进行哪些更改才能进入 O(N)。

【问题讨论】:

  • 一般情况下,如果循环内的语句为O(1),则1个循环为O(n),2个循环嵌套1个为O(n^2)O(n*m)
  • 假设这个post 会帮助你更清楚地理解时间复杂度的概念。
  • @SpencerWieczorek 只是好奇地问.. 给定的矩阵已经是二维数组,这意味着n is the size of the double array row*column 所以即使使用嵌套循环也不会是O(n),因为循环会循环n 时间?
  • 在最坏的情况下,嵌套循环将在 matrix[i] 中的每个元素完整运行一次,因此假设方阵为 O(N^2)。
  • @Luminous_Dev 这完全取决于您如何定义N 是什么,但通常您希望它是线性扩展的。声明 N=row*col 意味着虽然您可以声明它是 O(N),但它与矩阵行和列的大小不一致。

标签: java arrays time-complexity


【解决方案1】:

我认为搜索可以在线性时间内完成。将以下 4×4 矩阵视为视觉对象:

1 2 4 6
2 3 5 7      ascending from left to right
3 4 6 8      and from top to bottom
4 5 6 9

如果我们正在搜索值5,我们可以从左上角开始,然后向右走,直到找到该值,或者遇到一个大于目标 5 的数字。在此在这种情况下,我们达到了 6。然后,我们可以回滚到 4,并向下推进到更高的。保证第一行中的每个先前值都小于目标值,并且保证从该列开始的下一行中的每个值都大于第一行中的值。

这是一种大致线性的方法。一个很好的类比是绕着山的周边走,寻找一定的高度。如果在每个点我们要么找不到我们想要的高度,要么只找到太高的点,我们就继续走。

【讨论】:

    【解决方案2】:

    您编写它的方式(蛮力计算)的最坏情况时间复杂度为 O(N^2)。由于您说数组已排序,因此您可以改为实现binary search,它的最坏情况时间复杂度为 N(2*log(N))。

    【讨论】:

      【解决方案3】:

      假设一个 n x m 矩阵,您的算法是 O(n * m),因为它(可能)迭代所有行和列(即所有元素)。

      但是,存在一个 O(log(m + n)) 的算法。

      因为这是一个在线编码面试(我是通灵者),所以我只给你提示:

      • 给定坐标 (x, y) 处的元素,如何知道目标可能在哪里?
      • 如果将 x 和 y 分开处理会怎样?

      【讨论】:

      • 嗨,格伦,请告诉我我的回答有什么问题。我认为我走在正确的轨道上,但我现在正在使用手机。
      • @tim 你的算法是 O(n),但你可以在 O(log n) 中完成。如果不是从左上角开始,而是从中间开始,会发生什么?
      • @Bohemian 我不知道您如何涵盖所有可能性,因为行的值可能与列的顺序不一致。我想过将矩阵拆分为围绕当前中间的 4 个子矩阵,但在每一步中,您只能消除 4 个矩阵中的 1 个,并且必须搜索其他 3 个。
      • 对,我们可以使用分而治之的方法,有点合并排序的味道。在这种情况下,我们将从中间开始,然后决定是否需要走高或走低。同样,我们将降落在该小节的中间,然后重复。这是O(N lgN)
      • @tim 是的。找出目标在哪个象限,然后递归调用是最简单的方法。
      【解决方案4】:

      你说矩阵是有序的,可以用二分查找找到目标。并使用两个单独的一层循环,首先搜索行,然后搜索列。它是o(N / 2)。

      【讨论】:

      • 注意O(N/2)O(N)相同。
      • 是的,你是对的。但我认为这对需求来说并不是一个糟糕的实现
      【解决方案5】:

      如上所述,对于方阵,您的算法是 O(N*M) 或 O(N^2)。

      你可以用一个循环来完成:

      基本上从右上角开始检查单元格,如果数字太大则向左移动,如果数字太小则向下移动。如果你从两边的边缘掉下来,数字就不存在了。

      boolean searchMatrix(int target, int[][] mat)
      {
         int i = 0, j = mat[0].length;
         while (i < mat.length && j >= 0)
         {
            if (mat[i][j] == target)
            {
               return true;
            }
            else if (mat[i][j] < target)
            {
               i++;
            }
            else
            {
               j--;
            }
         }
         return false;
      }
      

      【讨论】:

      • 这个程序的 jave 复杂度是否为 O(n)@twain249
      • 最坏的情况是你必须向左走 N-1 并向下走 M-1 所以它是 O(M+N-2) 或 NxN O(2N-2)是 O(N)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-28
      • 1970-01-01
      相关资源
      最近更新 更多