【问题标题】:algorithm: trying to get the index from array where |A[i] - i| <=c in log(N) with a divide and conquer algorithm算法:试图从数组中获取索引 |A[i] - i| <=c in log(N) 使用分治算法
【发布时间】:2020-09-05 00:09:21
【问题描述】:

输入:一个排序数组 A(所有元素都是整数,并且按递增顺序不同)和 c(整数)

输出:返回一个随机选择的索引,使该索引满足要求:|A[i]-i| &lt;= c

在最坏的情况下,它应该在 O(logN) 时间内运行。

我最初的想法是二进制搜索索引i,这样A[i] = 0或最接近0。然后这个索引将数组分成2部分。

左边部分包含元素 0。

对于右边部分,运行一个类似于二分查找的算法来检查中间值,看看是否有A[mid]-mid &lt;=c,如果是,转到[mid+1, end]。但是,当我有以下示例时,我发现了这个问题:

c=2
i     0  1  2  3  4  5  6  7
A[i] -5 -4  -1 0  1  5  8  9

A[4] 不符合 |A[4]-4| &lt;=2 但它会包含在我的算法中。 所以我现在完全不知道这个问题......

【问题讨论】:

  • 想象一个数组,其中元素是A[i]-i。该数组保证按升序排序。所以你需要做的就是对最接近 0 的元素进行二分搜索。
  • @user3386109。它不是升序排序的。有绝对值。如果已排序,只需取第一个元素。无需搜索
  • @MadPhysicist 对于给定的示例,A[i]-i 的虚拟数组是 {-5,-5,-3,-3,-3,0,2,2}。在我看来,这似乎是上升的。通常情况下确实如此,因为 OP 指定 A 的元素是不同的,这意味着 A 的元素必须至少与索引一样快。
  • @גלעדברקן 当然是,但 OP 询问的是 abs(A[i] - i)。否则这简直是微不足道的
  • @גלעדברקן 是的,接近零的元素将数组分成两部分。然后,您可以对这两个部分进行二进制搜索,以在每个匹配条件的部分中找到离零最远的部分。

标签: python list algorithm sorting divide-and-conquer


【解决方案1】:

让我们看一下数据。它来自A,其中包含不同的排序整数,对于任何一对连续元素,A[i] &lt;= A[i + 1] - 1

这些元素的搜索关键字是A[i] - iA[i + 1] - i - 1。从不等式两边减去i 表明两个连续的键如果为正则相等或增加,如果为负则相等或减少。

如果问题不要求绝对值,解决起来将是微不足道的。您只需检查第一个元素,它要么满足那里的标准,要么没有元素。

绝对值意味着您的键可以减少、增加或稳定。递减区域总是在最小值的左边,递增的区域在右边。

你可以在log(N) 时间内找到最小值,这与二分搜索类似,但从两端开始。诀窍是找出中点的哪一侧为最小值。

从数组的两端和中心开始。为每一半选择一个中点。如果中间点小于中心,则最小值在那一半:将边界调整到那一半并继续。如果没有,那是你那一半的新端点。你最多会做2 * log(N/2) = O(log(N)) 操作。

当你的边界最多相差 1 时,你可以提前终止,或者你提前遇到满足条件的元素。

如果您确实需要一个随机元素,而不是任意元素,则需要在每一半中搜索满足条件的边界。这不会增加自 O(4 log(N/2)) = O(log(N)) 以来的复杂性。大概从该区间中选择一个随机数是O(1)

如有必要,我将最后一部分留给读者作为练习。

【讨论】:

    猜你喜欢
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-12-11
    • 2020-11-02
    • 2020-05-27
    • 2021-06-22
    • 1970-01-01
    • 2016-01-08
    相关资源
    最近更新 更多