荷兰国旗问题
给定一个数组arr,和一个数num,请把小于num的数放在数组的
左边,等于num的数放在数组的中间,大于num的数放在数组的
右边。
要求额外空间复杂度O(1),时间复杂度O(N)
解决思路:
遍历,如果index的值小于num,与less区域的下一个值交换并扩大less区域,index++;如果大于num,则more区域的前一个值交换,并扩大more区域,index不变,继续判断;如果相等,则index++。
代码实现:
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 };
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
使用荷兰国旗改进经典快排:随机快排
原理与荷兰国旗问题一样,但经典快排一次只解决一个值的,从数组的最后一个值为参考值,不断递归,而改进后的增加了等于区域,这个区域不用动。
代码实现:
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);
}
}
随机快排比经典快排更快,也是最常用的排序算法
时间复杂度:O(N*logN)
空间复杂度:O(logN)
绕开数据状态的常用方式:随机、哈希