荷兰国旗
## 一、荷兰国旗问题
1、啥是荷兰国旗问题
荷兰国旗是由红白蓝3种颜色的条纹拼接而成,如下图所示:
假设这样的条纹有多条,且各种颜色的数量不一,并且随机组成了一个新的图形,新的图形可能如下图所示,但不仅仅只有这一种情况:
需求是:把这些条纹按照颜色排好,红色的在上半部分,白色的在中间部分,蓝色的在下半部分,我们把这类问题称作荷兰国旗问题。
2、荷兰国旗问题的抽象
我们把荷兰国旗问题抽象成数组的形式是下面这样的:
给定一个整数数组和一个值M(存在于原数组中),要求把数组中小于M的元素放到数组的左边,等于M的元素放到数组的中间,大于M的元素放到数组的右边,最终返回一个整数数组,只有两个值,0位置是等于M的数组部分的左下标值、1位置是等于M的数组部分的右下标值。
进一步抽象为更加通用的形式是下面这样的:
给定数组arr,将[l, r]范围内的数(当然默认是 [ 0 - arr.length - 1 ]),小于arr[r](这里直接取数组最右边的值进行比较)放到数组左边,等于arr[r]放到数组中间,大于arr[r]放到数组右边。最后返回等于arr[r]的左, 右下标值。
3、解决的思路
定义一个小于区,一个大于区;遍历数组,挨个和arr[r]比较,
(1)小于arr[r],与小于区的后一个位置交换,当前位置后移;
(2)等于arr[r],当前位置直接后移;
(3)大于arr[r],与大于区的前一个位置交换,当前位置不动(交换到此位置的数还没比较过,所以不动)。
遍历完后,arr[r]和大于区的最左侧位置交换。
最后返回,此时小于区的后一个位置,大于区的位置,即是最后的等于arr[r]的左, 右下标值。
4、详细的参考代码
package 排序算法;
import java.util.Arrays;
public class 荷兰国旗 {
public static void main(String[] args) {
int num = 7;
int a[] = new int[]{1, 4, 5, 7, 8, 1, 2, 3};
int leftArea = 0;
int rightArea = a.length - 1;
for (int i = 0; i < a.length && i < rightArea; ) {
if (num < a[i]) {
// 与大于区域交换
int temp = a[i];
a[i] = a[rightArea];
a[rightArea] = temp;
// 大于于区域扩
rightArea--;
} else if (num > a[i]) {
// 与小于区域交换
int temp = a[i];
a[i] = a[leftArea];
a[leftArea] = temp;
// 小于区域扩
leftArea++;
i++;
} else {
i++;
}
}
Arrays.stream(a).forEach(System.out::println);
}
}