现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左到右依次为红球、白球、蓝球。
可以借鉴快速排序的思路,先看三路快速排序的实现
三路快速排序法
适用于有大量重复元素的排序。
public class Quick3Way {
public static void sort(Comparable[] a)
{
sort(a, 0, a.length-1);
}
private static void sort(Comparable[] a, int lo, int hi)
{
int M = 5;
if(hi <= lo + M) //小数组切换到插入排序
{
int N = hi - lo + 1;
for(int i = 1; i < N; i++)
{
for(int j = i; j > 0 && less(a[j], a[j-1]); j--)
exch(a, j, j-1);
}
return;
}
int lt = lo, i = lo + 1, gt = hi;
Comparable v = a[lo];
while(i <= gt)
{
int cmp = a[i].compareTo(v);
if(cmp < 0)
exch(a, lt++, i++);
else if(cmp > 0)
exch(a, i, gt--);
else
i++;
}
sort(a, lo, lt-1);
sort(a, gt + 1, hi);
}
private static boolean less(Comparable v, Comparable w)
{
return v.compareTo(w) < 0;
}
private static void exch(Comparable[] a, int i, int j)
{
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
private static void show(Comparable[] a)
{
for(int i = 0; i < a.length; i++)
System.out.print(a[i] + " ");
System.out.println();
}
public static boolean isSorted(Comparable[] a)
{
for(int i = 1; i < a.length; i++)
if(less(a[i], a[i-1]))
return false;
return true;
}
public static void main(String[] args)
{
String[] a = {"S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E"};
sort(a);
isSorted(a);
show(a);
}
}
荷兰国旗问题三指针法
为了方便讨论,用数字0表示红球,数字1表示白球,数字2表示篮球。所以最后问题转换为数字排列0、1、2.
- 当current指针所指元素为0时,与begin指针所指元素交换,而后current++, begin++;
- 当current指针所指元素为1时,不做任何交换,而后current++;
- 当current指针所指元素为2时,与end指针所指元素交换,而后current指针不动,end–。
import java.util.Arrays;
public class ThreePointSortTest {
private static void ThreePointSort(int a[])
{
int begin = 0;
int current = 0;
int end = a.length - 1;
while(current <= end)
{
if(a[current] == 0)
{
int t = a[current];
a[current] = a[begin];
a[begin] = t;
current++;
begin++;
}
else if(a[current] == 1)
current++;
else
{
int t = a[current];
a[current] = a[end];
a[end] = t;
end--;
}
}
}
public static void main(String[] args)
{
int a[] = {0,1,2,1,2,1,0,0,1,2,0,2,1};
ThreePointSort(a);
System.out.println(Arrays.toString(a));
}
}