【问题标题】:Revisit: 2D Array Sorted Along X and Y Axis重温:沿 X 轴和 Y 轴排序的二维数组
【发布时间】:2011-05-28 13:22:54
【问题描述】:

所以,这是一个常见的面试问题。已经有一个话题了,我已经读过了,但它已经死了,没有任何答案被接受。最重要的是,我的兴趣在于这个问题的形式更受限制,有几个实际应用。

给定一个二维数组,这样:

  • 元素是独一无二的。
  • 元素沿 x 轴和 y 轴排序。
  • 排序都不占主导地位,因此排序都不是次要排序参数。
  • 因此,对角线也被排序。
  • 所有种类都可以被认为是朝着同一个方向移动。就是说都是升,或者说都是降。
  • 从技术上讲,我认为只要您有 >/=/
  • 元素是数字类型,具有单周期比较器。
  • 因此,内存操作是大 O 分析中的主要因素。

你如何找到一个元素?只有最坏的情况分析才重要。

我知道的解决方案:
各种方法是:
O(nlog(n)),您分别处理每一行。
O(nlog(n)) 具有很强的最佳和平均性能。

O(n+m):
从一个非极端的角落开始,我们假设它是右下角。
设目标为 J。Cur Pos 为 M。
如果 M 大于 J,则向左移动。
如果 M 小于 J,则向上移动。
如果你两个都做不到,你就完了,J 不在场。
如果 M 等于 J,你就完成了。
最初在别处找到,最近从here 偷来的。

我相信我见过一个最坏情况为 O(n+m) 但最佳情况接近 O(log(n)) 的情况。

我对什么感到好奇:

现在,我已经满意地证明,天真的分区攻击总是转移到 nlog(n)。通常,分区攻击似乎具有 O(n+m) 的最优最坏情况,并且大多数不会在缺席的情况下提前终止。因此,我还想知道插值探针是否可能不比二元探针更好,因此我想到有人可能会认为这是一个集合交叉问题,集合之间的相互作用很弱。我的想法立即转向Baeza-Yates intersection,但我还没有时间起草该方法的改编版。然而,考虑到我怀疑 O(N+M) 最坏情况的最优性是可以证明的,我想我会继续问这里,看看是否有人可以将一个反论点拼凑在一起,或者将一个递归关系放在一起用于插值搜索。

【问题讨论】:

  • “元素沿x轴排序,y轴排序”——就是说,每一行排序,每一列排序?
  • 从技术上讲,它们也是沿对角线排序的,所以是的。
  • 在O(n+m)方法的描述中,你的意思是“如果J大于大于最大值,则目标不存在”,只比较K,T 最大?另外,我可能遗漏了一些东西,但如果目标位于 100 的左侧,[ 100 200 ; 50 199 ] 不是反例吗?
  • 可能是。我有时会混淆我的左手和右手......啊,我觉得我很密集。给我一三分钟。
  • *.com/questions/3723353/… 有一个可接受的答案,它看起来与您提出的 O(n+m) 解决方案非常相似。

标签: algorithm multidimensional-array set linear-algebra


【解决方案1】:

这是一个证明,它必须至少是Omega(min(n,m))。让n >= m。然后考虑在(i,j) 处具有所有0s 的矩阵,其中i+j < m,所有2s,其中i+j >= m,除了单个(i,j)i+j = m 具有1。这是一个有效的输入矩阵,1m 可能的位置。没有对数组的查询(除了1 的实际位置)可以区分那些m 可能的位置。因此,在最坏的情况下,您必须检查所有 m 位置,以及任何随机算法的至少 m/2 预期位置。

您的一个假设是矩阵元素必须是唯一的,而我没有这样做。但是,它很容易修复,因为您只需选择一个大数字X=n*m,将所有0s 替换为小于X 的唯一数字,所有2s 替换为大于X 的唯一数字,以及@ 987654342@ 和X

因为它也是Omega(lg n)(计数参数),所以它是Omega(m + lg n),其中n>=m

【讨论】:

    【解决方案2】:

    最佳 O(m+n) 解决方案是从左上角开始,它具有最小值。沿对角线向下向右移动,直到碰到一个其值 >= 给定元素的值的元素。如果元素的值等于给定元素的值,则返回 found 为真。

    否则,从这里我们可以通过两种方式进行。

    策略 1:

    1. 在列中向上移动并搜索给定元素,直到到达末尾。如果找到,则返回找到为 true
    2. 在行中向左移动并搜索给定元素,直到到达末尾。如果找到,则返回找到为 true
    3. 发现返回错误

    策略 2: 让 i 表示行索引, j 表示我们停止的对角线元素的列索引。 (在这里,我们有 i = j,顺便说一句)。让 k = 1。

    • 重复以下步骤直到 i-k >= 0
      1. 搜索 a[i-k][j] 是否等于给定元素。如果是,则返回发现为真。
      2. 搜索 a[i][j-k] 是否等于给定元素。如果是,则返回发现为真。
      3. 增量k

    1 2 4 5 6
    2 3 5 7 8
    4 6 8 9 10
    5 8 9 10 11

    【讨论】:

      最近更新 更多