leetcode 快速排序相关
荷兰国旗问题 leetcode 75
荷兰国旗问题便于理解快速排序中的partition过程,荷兰国旗问题,给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。将颜色按照0、1、2来表示,问题可以转化为将数组中的元素按照小于1、等于1和大于1的顺序排列。
思路:使用两个指针分别记录小于位置和大于的位置,遍历数组,遇到小于pivot的数就将其与小于位置的下一个位置调换,遇到等于的数就直接跳过,遇到大于pivot的数就将其与大于位置的前一个数交换位置。
class Solution {
public void sortColors(int[] nums) {
if (nums == null || nums.length == 0) return;
int target = 1;
int less = -1;
int more = nums.length;
for (int i = 0; i < nums.length && i < more; i++) {
if (nums[i] < target) {
less++;
swap(nums, i, less);
}else if (nums[i] > target) {
more--;
swap(nums, i, more);
i--;
}else {
continue;
}
}
}
public void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
快速排序 leetcode 912
完成荷兰国旗问题后,就可以引出快速排序问题。快速排序的基本思路为,将数组中最后一个数选定为pivot,将数组中第一个数到倒数第二个数之间的数组划分为小于pivot、等于pivot和大于pivot的部分,接着将数组最后一个数与记录大于部分位置的那个数调换位置,至此0~less为小于pivot的数(less记录小于位置), less+1到more为等于pivot的数,more+1到数组最后为大于pivot的数。然后,在对小于部分,和大于部分继续做partition过程直到所有数排序完成。
public class Solution {
public void sort(int nums) {
quickSort(nums, 0, nums.length-1);
}
public void quickSort(int[] nums, int L, int R) {
if (nums == null || nums.length < 2) return;
int[] p = partition(nums, L, R);
quickSort(nums, L, p[0]-1);
quickSort(nums, p[1]+1, R);
}
public int[] partition(int[] nums, int L, int R) {
if (L <= R) {
// 快排3.0 对数组进行打乱处理,避免最坏情况的时间复杂度O(N^2)
int ranIndex = L + (int)(Math.random()*(R-L+1));
swap(nums, ranIndex, R);
int less = L-1, more = R;
int pivot = nums[R];
for (int i = L; i < more; i++) {
if (nums[i] < pivot) {
less++;
swap(nums, i, less);
}else if (nums[i] > pivot) {
more--;
swap(nums, i, more);
i--;
}else {
continue;
}
}
swap(nums, more, R);
return new int[]{less+1, more};
}
}
}
leetcode K个最大元素 leetcode 215
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
该问题我认为比较好的解决方案是使用堆,但是为了加深对快排的理解,在这里使用快速排序选择的方式。
思路:在数组中随机选一个数作为pivot,将数组划分为大于等于小于三部分。之后,判断等于部分的最后一个数的位置是否恰好等于数组长度减k,若是则说明该数恰好为第k大的元素,若小于k则说明第k大的数在数组右边部分,对右边部分进行快速排序选择,若大于k则说明第k大的数在数组左侧,对左侧进行快速排序选择。
class Solution {
public int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length < k) return -1;
return partition(nums, 0, nums.length-1, k);
}
public int partition(int[] nums, int L, int R, int k) {
if (L <= R) {
int ranIndex = L + (int)(Math.random*(R-L+1));
swap(nums, ranIndex, R);
int less = L-1, more = R;
int pivot = nums[R];
for (int i = L; i < more; i++) {
if (nums[i] < pivot) {
less++;
swap(nums, i, less);
}else if (nums[i] > pivot) {
more--;
swap(nums, i, more);
i--;
}else {
continue;
}
}
swap(nums, more, R);
if (more == nums.length-k) return nums[more];
else if (more < nums.length-k) partiotion(nums, more+1, R);
else if (more > nums.length-k) partition(nums, L, more-1);
return nums[nums.length-k];
}
return -1;
}
public static void swap(int [] arr, int p1, int p2) {
int temp = 0;
temp = arr[p1];
arr[p1] = arr[p2];
arr[p2] = temp;
}
}
leetcode K个最小元素 leetcode 40
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
这道题思路与上述第k个最大值的思路基本相同。同样较好的结局方式是使用堆,这里使用快速选择排序的方法。
思路:随机选择数组中的一个数作为pivot,将数组划分为小于等于大于三部分,检查等于部分的第一个值,也就是less+1位置是否恰好等于k-1,若相等则说明从第一个数到less+1位置上的数就是k个最小元素,若小于k-1则说明k个最小元素在右边,若大于则说明k个最小元素在左边。
class Solution {
public int[] getLeastNumbers(int[] arr,int k) {
if(arr.length==0 || k==0) {
return new int[0];
}
//数组下标范围是0~length-1,枢纽元素下标是k-1
int[] nums = QuickSort(0,arr.length-1,arr,k-1);
return nums;
}
private int[] QuickSort(int left,int right,int[] arr,int k) {
int position = partition(left,right,arr);
//输入的是k=k-1,因此此处返回的是(k-1)+1个长度
if(position==k) return Arrays.copyOf(arr, k+1);
return position<k? QuickSort(position+1, right, arr,k):QuickSort(left, position-1, arr,k);
}
private int partition(int L, int R, int[] arr) {
int random = L + (int)Math.random()*(R-L+1);
swap(arr, random, R);
int pivot = arr[R];
int less = L-1, more = R;
for (int i = L; i < arr.length && i < more; i++) {
if (arr[i] <= pivot) {
less++;
swap(arr, i, less);
}else if (arr[i] > pivot) {
more--;
swap(arr,i,more);
i--;
}
}
swap(arr, more, R);
return less+1;
}
public void swap(int [] arr, int p1, int p2) {
int temp = 0;
temp = arr[p1];
arr[p1] = arr[p2];
arr[p2] = temp;
}
}