【问题标题】:Algorithm to find three numbers in an array such that a< b < c and v[a]<v[c]<v[b]在数组中找到三个数字的算法,使得 a< b < c 和 v[a]<v[c]<v[b]
【发布时间】:2019-05-04 03:49:27
【问题描述】:

给定一个整数向量,我需要找出向量中是否存在三个元素a, b, c,即a &lt; b&lt; cv[a] &lt; v[c] &lt; v[b]

到目前为止,我的方法如下。首先,我忘记了 a 并为向量中的每个数字找到位于该元素左侧的 v[i] 的最小值。我将此信息存储在另一个数组中。然后我应用归并排序,当我到达两个元素交叉的点时,我测试右元素是否可以是 c 而左元素是 b。但是,我还需要测试与正确元素交叉的其他元素是否可能是 b,这增加了太多时间复杂度。我最多需要它是线性的。 你能给我一个关于如何进行的提示吗?

编辑:请原谅,之前的标题不太好。我需要的是 a

EDIT2: 限制:我不能使用数据结构,除了向量。而且算法必须基于分治法

【问题讨论】:

  • 这样...?请发布您解决此问题的尝试。
  • 如果你使用的是 C++,你可以通过使用 std::find_if 两次来解决这个问题。
  • 我不太确定。条件是什么?

标签: algorithm vector data-structures divide-and-conquer


【解决方案1】:

您可以在 O(n) 时间和最坏情况 O(n) 时间内完成此操作通过在数组上迭代同时保持最大禁止范围(v[a]v[c])的堆栈(LIFO 数据结构)来获得空间。堆栈的最顶部元素是从迄今为止看到的最小值到自该最小值以来看到的最大值的范围。 (或者,出于实现原因,您可能会发现将该范围保存在单独的变量中更容易,并且仅将堆栈用于较旧禁止范围。)

处理任何单个元素最多可能需要 O(n) 时间(如果它必须将整个堆栈一直展开到第一个范围),但是这个成本必然是摊销的,因此处理整个数组仍然只有 O(n) 时间(因为处理一个元素会展开整个堆栈的唯一原因是如果它将所有禁止范围统一为一个更大的范围,在这种情况下,它不需要重新添加它弹出的所有范围,因此这项工作只完成一次) .

【讨论】:

  • 看起来不错,但我现在对这些数据结构并不熟悉。难道没有基于分而治之的解决方案吗?
  • @Seven:回复:“我现在对那些数据结构不熟悉”:这只是一种数据结构;详情请见https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
  • 我不太明白为什么一定要统一所有的禁区
  • 如果我们有序列 6,8,2,4,5 ,当达到 5 时,我们将不得不展开整个堆栈而不统一任何东西
  • @Seven:我没有在回答中提供“放松”的精确定义,因为我想把细节留给你自己弄清楚;但只要说在您的示例中,您不需要将范围 (6,8) 从堆栈中弹出,只要您有一种方法可以检查堆栈的最顶部元素而无需删除它就足够了。 (即使您不这样做 - 弹出并重新添加一个元素仍然是 O(1)。只要处理给定元素不涉及超过(比如说)两次调用push。)
猜你喜欢
  • 1970-01-01
  • 2021-10-07
  • 2011-03-24
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
  • 2018-04-17
相关资源
最近更新 更多