algorithm - 简化的 3 路分区排序的时间复杂度
问题描述
下面是我的算法,它是对通用列表的 Dijkstra 的 3 路分区算法的简化:
static <T extends Comparable> void dutchSort(List<T> list, int left, int right) {
if (left >= right) return;
T pivot = list.get(left);
// smaller - index of the last element smaller than pivot value
// equal - index of the last element equal to pivot value
// larger - index of the first element larger than pivot value
int smaller = left-1, equal = left, larger = right;
// before sorting is completed, 'equal' is the current value
// much like 'i' in a for-loop
// O(N) time
while (equal < larger) {
if (list.get(equal).compareTo(pivot) < 0)
Collections.swap(list, equal, ++smaller);
else if (list.get(equal).equals(pivot))
equal++;
else
Collections.swap(list, equal, --larger);
}
// recursively sort smaller subarray
dutchSort(list, left, smaller+1);
// recursively sort larger subarray
dutchSort(list, equal, list.size());
}
这是 O(1) 空间,我认为是 O(N^N) 时间,但我不确定。Toptal 在 3-way QuickSort 上的帖子说它是 O(N^2),但不同的是我的算法更加天真。我的思考过程是:while
循环需要 O(N) 时间,在最坏的情况下(所有 N 个元素都是不同的?)问题被分解为 N 个大小为 1 的子数组。
我尝试了主定理,但我不确定任何变量值。我认为子问题的数量是 2,每个递归调用将问题减少 2 倍,合并子问题需要 O(1) 的工作。
所有这一切都只是有根据的猜测,我很可能很迷茫,所以我真的很想严格解决时间复杂度。
O(N^N) 时间是否正确?如果是这样,为什么?
非常感谢 :)
解决方案
所以while
循环在初始调用时是 O(n)。如果我们假设一个数组[1, 2, 3, 4, 5]
,那么第一次通过循环list[equal] == pivot
,我们递增equal
。
通过循环的第二次和后续时间,list[equal] > pivot
,因此我们减少larger
并与该元素交换。当循环结束时,你有equal=1
,并且smaller
没有改变。您的递归调用变为:
dutchSort(list, 0, 0)
dutchSort(list, 1, n)
所以其中一件物品掉了下来。
对更多的递归深度做同样的心理练习,我想你会了解分区是如何工作的。
为了使您的算法为 O(N^N),它必须将每个元素与每个其他元素进行多次比较。但这不会发生,因为在每个递归级别,您都将问题分成两部分。一旦某些东西被分割到数组的左半部分,它就不能与移动到数组右半部分的东西进行比较。所以最坏的情况是每个元素都与其他元素进行比较。那将是O(N ^ 2)。
当所有元素相等时,算法为 O(N)。
我认为算法的复杂性取决于唯一项目的数量。初始数组顺序似乎不会产生任何影响。
推荐阅读
- java - 如何避免 Eclipse 中 Maven 项目的父 POM 问题?
- ef-core-2.1 - 连接已经在一个事务中,不能参与另一个事务
- ios - 用户在后台模式下收到通知时如何更改徽章编号
- javascript - Javascript:Is-SubArray 返回 false
- asp.net - WAPPALYZER vs Netcraft vs builtwith
- c# - 使用最小起订量对自动映射器进行单元测试
- c++ - 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- javascript - Websocket HTTPS 到 HTTP 降级
- bash - bash cp 带空格的文件名
- flutter - iPhone 5 上的 Flutter 共享首选项崩溃(无效的 radix-16 数字)