1.引入:荷兰国旗问题,让数组分为三块,一种小于num,一种大于num,一种等于num,如下图所示。
方法:i<num,则小于区域往右扩展,i++;
i==num,则i++;
i>num,则i和大于区前一个数交换,大于区往左扩,i原地不动。(原地不动是因为换完之后i那个位置还没被看)
当大于区域和i撞上了,则i停止往前。
如下图所示。
代码如下:
public static void swap(int[] arr,int i,int j)
{
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
public static void partition(int[] arr,int num)
{
int left=-1;
int right=arr.length;
int i=0;
while(i<right)
{
if(arr[i]<num)
{
left++;
if(left!=i)
{
swap(arr,left,i);
}
i++;
}
else if(arr[i]>num)
{
right--;
swap(arr,i,right);
}
else
{
i++;
}
}
}
补充一个java交换函数的方法:直接传数组的引用和位置,然后交换即可。
2.快排:就是不断递归荷兰国旗问题里面划分的大于和小于的小块,知道划分地不能再划分为止即可。
快排进阶版本:给定两个指针,在数组左右移动,划分称小于等于num,大于num这两个部分,然后进行划分。num就是随机选一个。时间复杂度O(N*logN)。
代码如下所示:
public static void swap(int arr[],int i,int j){
int tem=arr[i];
arr[i]=arr[j];
arr[j]=tem;
}
public static void quickSort(int[] arr){
if(arr==null||arr.length<2){
return;
}
quickSort(arr,0,arr.length-1);
}
public static void quickSort(int[] arr,int L,int R){
if(L<R){
swap(arr,L+(int)(Math.random()*(R-L+1)),R);
int[] p=partition(arr,L,R);
quickSort(arr,L,p[0]-1);
quickSort(arr,p[1]+1,R);
}
}
public static int[] partition(int[] arr,int L,int R){
int less=L-1;
int more=R;
while(L<more){
if(arr[L]<arr[R]){
swap(arr,++less,L++);
}else if(arr[L]>arr[R]){
swap(arr,--more,L);
}else{
L++;
}
}
swap(arr,more,R);
return new int[]{less+1,more};
}
代码解释:partition功能是返回传入数组大于某个值和小于某个值的左边界和右边界,以数组形式返回。