algorithm - 荷兰国旗问题

给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边


思路分析

首先它没要求左右两边有序,所以我们可以根据下面步骤实现:

  • arr[i]<num,就将arr[i]和小于区下一个交换,小于区右扩
  • arr==num,i++
  • arr[i]>num,就将arr[i]和大于区前一个交换,大于区左扩,[i]原地不变

java

相关代码:快速排序

public static void main(String[] args) {
    int[] arr = {3, 5, 6, 3, 4, 5, 2, 6, 9, 0};
    int num = 3;	// 要求左边比3小,中间等于3,右边比3大
    dutchFlag(arr, num);
    System.out.println(Arrays.toString(arr));
}

public static void dutchFlag(int[] arr, int num) {
    if (arr == null || arr.length < 2) return;

    dutchFlag(arr, 0, arr.length - 1, num);
}

public static void dutchFlag(int[] arr, int L, int R, int X) {
    if (L >= R) return;
    
    // 不需要递归,因为题目没说左右要有顺序
	partition(arr, L, R, X);
}

// 分区函数,将arr分为:【小于区,等于区,大于区】
public static void partition(int[] arr, int L, int R, int X) {
    int less = L - 1;
    int more = R;
    // 此处跟快排的区别是:快排最后会将基准值和右区左边界值左交换,并返回基准值坐标然后递归
    while (L <= more) {
        if (arr[L] < X) {
            swap(arr, ++less, L++);
        } else if (arr[L] > X) {
            swap(arr, more--, L);
        } else {
            L++;
        }
    }
}

public static void swap(int[] arr, int i, int j) {
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}

文档信息

Search

    Table of Contents