【问题标题】:Finding a specific ratio in an unsorted array. Time complexity在未排序的数组中查找特定比率。时间复杂度
【发布时间】:2012-12-30 18:59:16
【问题描述】:

这是家庭作业。

目标是用伪代码提供一种算法,该算法将搜索数字数组(不指定整数或 >0)并检查任何两个数字的比率是否等于给定的 x。时间复杂度必须在 O(nlogn) 以下。

我的想法是对数组进行归并排序(O(nlogn) 时间),然后如果 |x| > 1 开始按降序检查每个数字(使用二进制遍历算法)。检查每个数字也应该花费 O(logn) 时间,最坏的情况是 n 次检查总共需要 O(nlogn)。如果我没有遗漏任何东西,这应该给我们一个 O(nlogn) + O(nlogn) = O(nlogn) 的最坏情况,在分配的参数内。

我意识到排序后从哪里开始检查比率并不重要,但时间成本按 1/2 摊销)。

我的逻辑正确吗?有更快的算法吗?

如果不清楚,举个例子:

给定一个数组 { 4, 9, 2, 1, 8, 6 }

如果我们要搜索比率为 2:

  1. 合并排序 { 9, 8, 6, 4, 2, 1 }

  2. 由于给定的比率 >1,我们将从左到右搜索。

2a。第一个数字是 9。检查 9 / 4 > 2。检查 9/6

【问题讨论】:

    标签: algorithm optimization complexity-theory big-o mergesort


    【解决方案1】:

    您提出的分析是正确的,是解决此问题的绝佳方法。排序确实在 O(n log n) 时间内起作用,并且 2n 二进制搜索也需要 O(n log n) 时间。也就是说,我认为您不想在这里使用“摊销”一词,因为它指的是不同类型的分析。

    作为如何加快解决方案速度的提示,您的解决方案的总体思路是可以有效地查询任何数字,该数字是否存在于数组中。这样,您可以遍历所有数字并寻找任何可以使比率起作用的东西。但是,如果您在数组外部使用支持快速访问的辅助数据结构,则可能会以增加内存使用量为代价来减少运行时间。尝试考虑哪些数据结构支持非常快速的访问(例如,O(1) 查找),看看您是否可以在这里使用它们。

    希望这会有所帮助!

    【讨论】:

    • 我还是一名本科生,任何对技术术语的滥用(我希望)都可以原谅。如果我理解正确(并且可能需要查找一些来源:我为这些值创建了一个哈希表,将当前数字除以所需的比率“x”并检查这个 n/x 是否存在?O(1) 访问哈希意味着没有冲突,问题是,解析数据以创建完美的哈希函数可能会增加复杂度。这可以在 O(nlogn) 下解决吗?
    • @GCon- 如果您使用标准哈希表,则查找的 预期 运行时将为 O(1),因此 预期算法的运行时间为 O(n)。大多数哈希表都有这个运行时发生的概率很高,所以退化到像 O(n log n) 这样的可能性很低。但是,如果您对此感到担忧,一种选择是采用混合策略,使用哈希表,如果冲突数量超过看起来“合理”的数量,则回退到 O(n log n) 解决方案。也就是说,发生这种情况的几率非常低,通常不值得担心。
    • 非常感谢!我还想问 - 可能是题外话(但我确信这不值得提出一个新问题:在算法分析中,摊销的确切定义是什么?我的印象是简化运行时间(但不一定按一个数量级)计为摊销。就像使用保护节点进行 BST 查找一样,平均时间相同,但每个节点的评估少?
    • @GCon- 摊销是指通过查看所有操作完成的工作总量而不是任何单个操作来分析算法或数据结构。例如,在最坏的情况下,将一个值附加到动态数组可能需要 O(n) 时间(如果您必须将数组加倍并复制所有旧值),但如果您查看所有工作的总和将 n 个元素添加到动态数组后,运行时间仅为 O(n),而不是 O(n^2),因为 O(n) 操作很少发生。将工作减少一个常数因子是好的,但不是摊销。
    【解决方案2】:

    要解决这个问题,只需要 O(nlgn) 就足够了

    第一步,对数组进行排序。花费 O(nlgn)

    第二步,检查比例是否存在,这一步只需要o(n)

    你只需要两个指针,一个指向第一个元素(最小的),另一个指向最后一个元素(最大的)。

    计算比率。

    如果比率大于指定的比率,则将第二个指针移动到其前一个元素。

    如果比率小于指定的比率,则将第一个指针移动到其下一个元素。

    重复上述步骤,直到:

    1. 你找到准确的比例,或者

    2. 要么第一个指针到达终点,要么第二个指针到达起点

    【讨论】:

    • 据我所知,O(nlogn) + O(nlogn) == O(nlogn) + O(n)。使用这种方法有什么好处吗?
    • @GCon 当然这种方法更好。如果你有大量的查询,比如 m 个查询,这个方法的时间复杂度为 O(nlg(n))+O(nm),这篇文章中的其他方法花费 O( nlg(n))+O(nlg(n)*m)。如果 m>>n, O(n*lg(n)) 部分可以省略。
    【解决方案3】:

    您的算法的复杂度是 O(n²),因为在对数组进行排序后,您会迭代每个元素(最多 n 次)并且在每次迭代中您最多可以执行 n - 1 个部门。

    相反,在对数组进行排序后,对每个元素进行迭代,并在每次迭代中将元素除以比率,然后查看结果是否包含在数组中:

    • 除法:O(1)
    • 在排序列表中搜索:O(log n)
    • 对每个元素重复:n

    导致时间复杂度 O(n log n)

    在你的例子中:

    • 9/2 = 4.5(未找到)
    • 8/2 = 4(找到)

    【讨论】:

    • 你能解释一下算法是如何O(n^2)的吗?我不明白这对你声称的那么多部门有何影响。
    • 想象您的数组是 {9, 7, 5, 3, 2, 1}:乘以 9,您将进行 5 个除法,乘以 7,您将进行 4,乘以 5,您将制作 3...
    • 也许我误解了算法。我对 OP 方法的理解是(1)对所有内容进行排序,然后(2)对每个数组元素 n,对数组中的 rn 和 n / r 进行二进制搜索。结果,每个元素的分割数仅为 O(log n),而不是每个元素的 O(n)。这似乎只做 O(n log n) 工作。我是否误解了 OP 的建议?
    • 这确实是正确的方法。我的建议是只搜索 n / r,在这两种情况下,复杂度都是 O(n log n)
    • 我现在意识到你已经回答了我的问题。再次非常感谢!
    【解决方案4】:

    (1) 构建此数组的哈希图。时间成本:O(n)

    (2) 对于每个元素 a[i],在 HashMap 中搜索 a[i]*x。时间成本:O(n)。

    总成本:O(n)

    【讨论】:

      猜你喜欢
      • 2013-04-01
      • 2014-10-12
      • 1970-01-01
      • 1970-01-01
      • 2023-01-16
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      • 2017-12-18
      相关资源
      最近更新 更多