荷兰国旗问题描述(简化版)
给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度 O(N)
本题解法
关于荷兰国旗问题其他帖子已经给出了非常详尽的解法描述,我在这里就只是简单概括一下:给定数arr,数组的左边界为l,右边界为r,以arr[r]为划分值。设置一个窗口lp,窗口初始值设为l-1,设置一个指针p从l开始往后遍历。如果arr[p] <= arr[r],指针所指向的数和arr[lp + 1]交换位置,p++。如果arr[p] > arr[r],p++。
最终arr[r]和arr[lp+1]交换位置,返回lp+1。
本题易错点
虽然返回的是划分值的位置,但是划分值最终所在位置并不一定是在arr的中间,而是有可能处在arr最左边或者最右边(当arr中在给定范围内的数全部小于r,或者全部大于r的时候就可能发生这种情况),因此需要规避掉方法中传入的l比r大的情况
代码
public static void quickSort4(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
process4(arr, 0, arr.length - 1);
}
public static void process4(int[] arr, int l, int r) {
if(l > r){
return;
}
if(l == r){
return;
}
int m = partition1(arr, l, r);
process4(arr, l, m - 1);
process4(arr, m + 1, r);
}
public static int partition1(int[] arr, int l, int r) {
int p = l;
int lp = l - 1;
while (p < r){
if(arr[p] <= arr[r]){
swap1(arr,p++,++lp);
}
else{
p++;
}
}
swap1(arr,(lp+1),r);
return (lp + 1);
}
public static void swap1(int[]arr,int a,int b){
int t = arr[a];
arr[a] = arr[b];
arr[b] = t;
}