以下算法在未排序数组中找到最小值的复杂性

Posted

技术标签:

【中文标题】以下算法在未排序数组中找到最小值的复杂性【英文标题】:Complexity of the following algorithm to find minimum value in an unsorted array 【发布时间】:2019-04-06 22:47:26 【问题描述】:

通过使用分治法,如果我们将一个数组重复分成两半,直到它们减小到两个大小 - 之后我们可以在 O(1) 时间内返回两者中的最小值。扩展该方法,为了将两个子数组 A 和 B 分别与它们的最小值 'a' 和 'b' 合并,我们可以在 O(1) 时间内直接返回它们的最小值——使合并步骤成为一个恒定时间操作。

这实质上意味着存在 logN 个级别,合并步骤的复杂度为 O(1)。那么这是否意味着使用该算法在未排序数组中找到最小值的复杂度为 O(logN)?

另外,请参阅此讨论。

Finding the minimum in an unsorted array in logarithmic time

【问题讨论】:

递归树 分支 乘以 2。您将拥有指数级的子数组。 【参考方案1】:

甚至不看你的算法,O(Log N) 就永远不可能找到最小值。

因为无论采用何种策略,在您看到所有元素之前都无法知道最小值。 (在未排序的数组中,读取一个元素绝对不会提供其他元素的信息。)

因此寻找最小值是一个 Ω(N) 问题。

【讨论】:

【参考方案2】:

之后我们可以在 O(1) 时间内返回两者中的最小值。

您确实在恒定时间内比较了一对值,但您有 n/2 对值要比较。这使得第一步总共为 O(n/2)(这已经是 O(n)),并且总结每一步得到 O(n/2 + n/4 + n/8 + ...)。

简而言之,您仍然需要进行至少 n-1 次比较。没有任何漏洞。

【讨论】:

【参考方案3】:

虽然 Nelfeal Yves Daoust 回答得很好,但我想补充一些评论。

只有未排序的数组,没有其他方法可以在亚线性时间内找到最小值/最大值。由于我们不知道哪个元素最大或最小,因此您必须全部查看。

实际改进

如果我们在数据结构上允许更多的操作和空间,我们可以让它更快。

数组为空

Insert(e):使用 e 的值设置最小值/最大值。 O(1) Remove(e):返回一些预定义的值。 O(1) Minimum/Maximum(e):返回一些预定义的值。 O(1)

数组非空

Insert(e):将 e 的值与最小值/最大值进行比较。如果满足条件,则使用 e 的值设置最小值/最大值。 O(1) Remove(e) : 如果最小值/最大值 == e ,则将最小值/最大值设置为未知(可能为 NULL?)。否则,只需从数组中删除 e 。 O(1) Minimum/Maximum(e) :如果最小值/最大值未知,则使用 O(N) 算法查找并设置最小值/最大值。如果已知最小值/最大值,则返回它。 O(N) 或 O(1)。

优点和缺点

插入/删除和最小/最大之间的操作比率决定了该算法的性能。 如果最小/最大操作的数量大于插入/删除,从概率上讲,随着数组变得越来越大,该算法的工作速度更快。

【讨论】:

您正在尝试解决一个不同的问题,即最小/最大值的动态维护。 Remove(e) 可以在 O(1) 时间内完成是错误的。

以上是关于以下算法在未排序数组中找到最小值的复杂性的主要内容,如果未能解决你的问题,请参考以下文章

基于Java实现的选择排序算法

如何在未排序数组的情况下找到未排序数组中的第k个最小整数?

java算法 直接选择排序

[经典] 在未排序数组中返回topK大的数

选择排序

选择排序