

荷兰国旗问题与快速排序算法 - Grey Zeng
source link: https://www.cnblogs.com/greyzeng/p/16739515.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

荷兰国旗问题与快速排序算法
作者:Grey
原文地址:
荷兰国旗问题#
给定一个整数数组,给定一个值K,这个值在原数组中一定存在,要求把数组中小于K的元素放到数组的左边,大于K的元素放到数组的右边,等于K的元素放到数组的中间。
时间复杂度要求O(N)
,空间复杂度要求O(1)
。
设置两个变量l
和r
,其中<i
位置的值都是比 K 小的数,i……r
都是等于 K 的数,>r
都是大于 K 的数。
初始值l = - 1, r = arr.length;
表示都还没考察过数组的任何一个元素,然后开始遍历数组,遍历到的位置为i
,arr[i]
有三种情况
arr[i] > K
arr[i] == K
arr[i] < K
对于情况 1, 只需要将i
位置的值和r - 1
位置的值交换,然后r--,i++
;
对于情况 3, 只需要将i
位置的值和l + 1
位置的值交换,然后l++,i++
;
对于情况 2, 只需要将i
位置的值和r-1
位置的值交换,然后i++
。
数组遍历完毕后,原始数组就形成了:小于K的元素放到数组的左边,大于K的元素放到数组的右边,等于K的元素放到数组的中间。
完整代码见
class Solution {
public static void sortColors(int[] arr) {
int l = -1;
int r = arr.length;
int i = 0;
while (i < r) {
if (arr[i] > 1) {
swap(arr, i, --r);
} else if (arr[i] < 1) {
swap(arr, i++, ++l);
} else {
// arr[i] == 1
i++;
}
}
}
private static void swap(int[] arr, int l, int r) {
if (l == r) {
return;
}
arr[l] = arr[l] ^ arr[r];
arr[r] = arr[l] ^ arr[r];
arr[l] = arr[l] ^ arr[r];
}
}
快速排序#
基于上述荷兰国旗算法的原型,我们可以实现快速排序算法,流程是
在arr[L……R]
范围上,进行快速排序的过程如下
0)在这个范围上,随机选一个数记为num
,
1)用num
对该范围使用荷兰国旗算法,< num
的数在左部分,== num
的数中间,> num
的数在右部分。假设== num
的数所在范围是[a,b]
2)对arr[L..a-1]
进行快速排序(递归)
3)对arr[b+1..R]
进行快速排序(递归)
因为每一次荷兰国旗算法都会搞定一批数的位置且不会再变动,所以排序能完成
1)通过分析知道,划分值越靠近中间,性能越好;越靠近两边,性能越差
2)随机选一个数进行划分的目的就是让好情况和差情况都变成概率事件
3)把每一种情况都列出来,会有每种情况下的时间复杂度,但概率都是1/N
4)那么所有情况都考虑,时间复杂度就是这种概率模型下的长期期望!
时间复杂度O(N*logN)
,额外空间复杂度O(logN)
都是这么来的。
题目链接:LintCode 464 · Sort Integers II
完整代码见
public class Solution {
/**
* @param a: an integer array
* @return: nothing
*/
public static void sortIntegers2(int[] arr) {
if (null == arr || arr.length < 2) {
return;
}
process(arr, 0, arr.length - 1);
}
public static void process(int[] arr, int s, int e) {
if (s >= e) {
return;
}
swap(arr, e, s + (int) (Math.random() * (e - s)));
int[] range = sortColors(arr, s, e);
process(arr, s, range[0] - 1);
process(arr, range[1] + 1, e);
}
public static void swap(int[] arr, int i, int j) {
if (i == j) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
public static int[] sortColors(int[] arr, int s, int e) {
int l = s - 1;
int r = e + 1;
int p = arr[e];
int i = s;
while (i < r) {
if (arr[i] > p) {
swap(arr, i, --r);
} else if (arr[i] < p) {
swap(arr, i++, ++l);
} else {
i++;
}
}
return new int[]{l + 1, r - 1};
}
}
更多#
参考资料#
Recommend
-
100
数据结构与算法—快速排序(Java实现)
-
26
算法原理 下列动图来自 @五分钟学算法 ,演示了快速排序算法的原理和步骤。 步骤: 从数组中选...
-
41
夯实算法-快速排序 2020-03-01 / / 168 点击 / 阅读耗时 7 分钟...
-
16
微信搜索:mag:「码农田小齐」,关注这个在纽约的程序媛,回复「01-05」可以获取计算机精选书籍、个人刷题笔记、大厂面经、面试资料等资源,么么哒~
-
10
快速选择算法详解 👆让天下没有难刷的算法!若 GitBook 访问太慢,可尝试
-
7
快速排序与冒泡排序类似,也属于交换排序,通过元素之间的比较和交换位置实现排序。不同的地方在于,冒泡排序在每一次循环只把一个元素冒泡到数组的一端,而快速排序在每一轮挑选一个枢纽元,并让其他比它大的元素移动到数组的一边,...
-
4
有向无环图的拓扑排序 作者:Grey 原文地址: 博客园:有向无环...
-
4
单链表的排序问题 作者:Grey 原文地址: 博客园:单链表的排序问题
-
11
在链表上实现 Partition 以及荷兰国旗问题 作者:Grey 原文地址:
-
5
基于桶的排序之计数排序 作者:Grey 原文地址: 博客园:基于...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK