java - 使用枢轴元素对数组进行分区的算法

标签 java arrays algorithm

我试图解决一些 java 编程书籍中的以下编程练习

Write method that partitions the array using the first element, called a pivot. After the partition, the elements in the list are rearranged so that all the elements before the pivot are less than or equal to the pivot and the elements after the pivot are greater than the pivot. The method returns the index where the pivot is located in the new list. For example, suppose the list is {5, 2, 9, 3, 6, 8}. After the partition, the list becomes {3, 2, 5, 9, 6, 8}. Implement the method in a way that takes at most array.length comparisons.

我已经实现了解决方案,但它需要的不仅仅是array.length 比较。

这本书本身有解决方案,但不幸的是它完全错误(不适用于某些输入)。我已经看到了 this 的答案类似的问题,并了解 Quicksort 算法的“征服”部分,但在此算法中,值使用中间值进行分区,但在我的例子中,需要使用第一个数组值作为基准。

最佳答案

这是链接答案中的枢轴例程(改编自 source here )。

    int split(int a[], int lo, int hi) {
        // pivot element x starting at lo; better strategies exist
        int x=a[lo]; 

        //  partition
        int i=lo, j=hi;
        while (i<=j) {
            while (a[i]<x) i++;
            while (a[j]>x) j--;
            if (i<=j) swap(a[i++], a[j--]);
        }

        // return new position of pivot
        return i;
    }

本算法中元素间比较的次数为n或n+1;因为在每个主循环迭代中,ijc 个单位靠得更近,其中 c 是在每个内部 while 循环中执行的比较次数。看看那些内部循环 - 当它们返回 true 时,ij 将靠近 1 个单位。如果它们返回 false,那么在主循环结束时,ij 将因为交换而靠近 2 个单位。

此 split() 可读性强且简短,但它也有一个非常糟糕的最坏情况(即,枢轴在两端结束;点击第一个链接查看结果)。如果数组已经向前或向后排序,就会发生这种情况,这实际上非常频繁。这就是其他枢轴位置更好的原因:如果您选择 x=a[lo+hi/2],最坏情况将不太常见。更好的是 do like Java ,并花一些时间寻找一个好的支点,以避开最坏的情况。如果您点击 Java 链接,您将看到一个更复杂的枢轴例程,它可以避免在有许多重复元素时做额外的工作。

关于java - 使用枢轴元素对数组进行分区的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31067261/

相关文章:

algorithm - 跳转搜索为什么不能用二分查找代替线性查找呢?

java - 具有类和接口(interface)的类型变量 : inheritence problems

JavaScript - 对同一行和同一列中的值求和

python - Numpy 3d 数组索引

c# - 我如何确定在我的 2048 实现中移动和合并了哪些图 block ?

python - Dijkstra 的算法只是 BFS,您还计算节点权重吗?

java - 将 JIRA 5.1 升级到 JIRA 6

java - 如何让错误显示出来

java - Netty Nio 中 promise 的异步更新

c++ - 在字节数组上转换具有虚函数的结构是否安全?