简化三维分区排序的时间复杂度

时间:2018-04-26 01:24:07

标签: algorithm sorting time-complexity space-complexity master-theorem

下面是我的算法,它简化了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's post on 3-way QuickSort说它是O(N ^ 2),但区别在于我的算法更天真。我的思考过程是:while循环需要O(N)时间,在最坏的情况下(所有N个元素都不同?)问题被分解为大小为1的N个子数组。

我尝试了主定理,但我不确定任何变量值。我认为子问题的数量是2,每个递归调用将问题减少2倍,并且合并子问题需要O(1)工作。

所有这些只是受过教育的猜测,而且我很可能很漂亮,所以我非常想严格解决时间复杂问题。

O(N ^ N)时间是否正确?如果是这样,为什么?

非常感谢:)

1 个答案:

答案 0 :(得分:1)

因此while循环在初始调用时为O(n)。如果我们假设一个[1, 2, 3, 4, 5]数组,那么第一次通过循环list[equal] == pivot,我们会增加equal

循环的第二次及以后的时间list[equal] > pivot,所以我们递减larger并与该元素交换。循环完成后,您equal=1smaller未更改。您的递归调用变为:

dutchSort(list, 0, 0)
dutchSort(list, 1, n)

所以其中一件物品掉了下来。

对于更多的递归深度进行相同的心理练习,我认为您将了解分区的工作原理。

对于你的算法是O(N ^ N),它必须多次将每个元素与每个其他元素进行比较。但这不会发生,因为在每个递归级别,您将问题分成两部分。一旦某些东西被分成数组的左半部分,它就无法与移动到数组右半部分的东西进行比较。所以最糟糕的情况是每个元素都与其他元素进行比较。那将是O(N ^ 2)。

当所有元素相等时,算法为O(N)。

我认为算法的复杂性取决于唯一项目的数量。初始数组顺序似乎没有任何影响。