引言:
解答:
需要准备3个下标
如果当前数字=num,cur跳下一个
如果数组中的当前数字<num,把这个数(3)和小于区域的下一个数(5)交换
然后小于区域扩一下
然后cur跳下一个位置
数组中的当前数字<num,把这个数(2)和小于区域的下一个数(5)交换,
然后小于区域扩一下
然后cur跳下一个位置
PS:
如果一上来遇到的就是cur<num
把这个数(3)和小于等于区域的下一个数(3)交换【自己和自己交换】
数组中的当前数字>num,把这个数(7)和大于区域的前一个数(x)交换
然后大于区域向左扩一个位置,more移动一下
然后让cur停留在原地,继续考察换过来的x跟num的大小关系
当cur == more的时候,整个过程停止
public class Code_08_NetherlandsFlag { public static int[] partition(int[] arr, int L, int R, int num) { int less = L - 1; int more = R + 1; while (L < more) { if (arr[L] < num) { swap(arr, ++less, L++); } else if (arr[L] > num) { swap(arr, --more, L); } else { L++; } } //less + 1:等于区域的第一个位置,more - 1:等于区域的最后 一个位置 return new int[] { less + 1, more - 1 }; } // for test public static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } }
传统快排:与荷兰国旗问题类似
import java.util.Arrays; //利用荷兰国旗问题进行快排 public class QuickSort { public static void main(String[] args) { int[] arr = {3,1,4,5,2,2,0,13}; System.out.println(Arrays.toString(arr)); // int[] res = new int[2]; // res = partition(arr, 0, arr.length-1); // System.out.println(res[0]+" " +res[1]); // System.out.println(Arrays.toString(arr)); quickSort(arr, 0, arr.length-1); System.out.println(Arrays.toString(arr)); } public static void quickSort(int[] arr,int L,int R){ if (L>=R) { return; } int[] p = partition(arr, L, R); quickSort(arr, L, p[0]-1); quickSort(arr, p[1]+1, R); } //以数组的最后一个数字arr[R]作为num //返回等于区域的下标 public static int[] partition(int[] arr,int L ,int R){ int less = L-1; int more = R+1; int num = arr[R]; while (L < more) { if (arr[L]==num) { L++; }else if (arr[L]<num) { swap(arr,++less,L++); }else if (arr[L]>num) { swap(arr,L ,--more ); } } int[] res = {less+1,more-1}; return res; } public static void swap(int[] arr, int i, int j ){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } }
经典快排存在的问题:
如果是一个有序的数组,算法的时间复杂度是O(N^2)
如果所选的num刚好把数组平分为左:<num;右>num,算法的时间复杂度是O(N*logN)
一次只搞定了7这一个数字
下一次在<7的区间里,只搞定了6,划分为<6的区域和=6的区域
每一次都是一次O(N),所以总的是O(N^2)
或者
解决方法:随机快排
随机找到一个数,把这个数和最后一个数字交换,进行快排
这样最差情况就是在某个概率的情况下出现的,此时时间复杂度就是一个概率事件
此时时间复杂度的长期期望:O(N*logN)
快排的额外空间复杂度:O(logN)
空间用在记录划分点