力扣912 排序数组 (快速排序)两种分区写法 java实现 - 教程
给你一个整数数组 nums,请你将该数组升序排列。
你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n)),并且空间复杂度尽可能小。
例如:输入:nums = [5,2,3,1] 输出:[1,2,3,5]
根据题目要求,该题对时间复杂度有要求,而且不能调用内置函数,所以就是手写快速排序
一、首先是最常规的双指针,从边界处开始选取基准元素进行排序,然后递归排序。
首先选取一个基准元素,例如:[5,2,3,1],选取5作为基准元素,将比5的小元素放在5左侧,将比5大的元素放在5右侧,用代码实现就是用双指针,记录基准元素值,若左指针位置小于右指针位置则进入循环若大于等于基准元素则右侧左移,直到找到小于基准元素的值或者到最左侧为止,将右指针元素复制到左指针位置。接着左指针元素小于等于基准元素则将左指针右移,直到找到大于基准元素的值或者到最右侧为止,将左指针元素复制到右指针位置上。最终将基准元素放到两个指针相遇位置。第一轮的排序结果就是[1,2,3,5]。
public static void main(String[] args) {
int[] nums = {110, 100, 0};
System.out.println(Arrays.toString(sortArray(nums)));
}
public static int[] sortArray(int[] nums) {
helper(nums, 0, nums.length - 1);
return nums;
}
public static void helper(int[] nums, int left, int right){
if (left >= right || left < 0 || right < 0){ // 若当前左指针大于等于右指针,或者左右指针小于0则返回,否则进入函数
return;
}
int i = left; // 设置左右指针位置。
int j = right;
int target = nums[i]; // 设置基准元素
while (i < j){ // 若左指针小于右指针则继续循环
while (i < j && nums[j] >= target){ // 当左指针小于右指针且右指针元素大于等于基准元素则右指针左移直到找到小于基准元素的值或者到最左侧
j --;
}
nums[i] = nums[j]; // 将右指针元素移到左指针位置
while (i < j && nums[i] <= target){ // 当左指针小于右指针且左指针元素小于等于基准元素则左指针右移直到找到大于基准元素的值或者到最右侧
i++;
}
nums[j] = nums[i];
}
nums[i] = target;
helper(nums, left, i - 1); // 递归最终位置左侧
helper(nums, i + 1, right); // 递归最终位置右侧
}
但考虑过后实际本质还是分区,还可以通过其他方式进行分区。
二、通过快慢指针进行分区,通过快慢指针进行分区
设置快慢指针,使得快慢指针都从当前分区开始处出发。例如[5,2,3,1],快慢指针都从nums[0],处出发也就是5的位置出发,基准元素为右侧边界元素,即1,若当前快指针值小于等于1(基准元素)则交换快慢指针元素,并将快慢指针加一,若当前快指针值大于1(基准元素)则将快指针右移一位,慢指针不动,直到快指针到达右边界,交换快慢指针元素,此时,慢指针左侧位置的值均小于基准元素,右侧的值均大于基准元素。第一轮排序后的数组为[1,2,3,5]
public static void main(String[] args) {
int[] nums = {-4,0,7,4,9,-5,-1,0,-7,-1};
System.out.println(Arrays.toString(sortArray(nums)));
}
public static int[] sortArray(int[] nums) {
quickSort(nums, 0, nums.length - 1);
return nums;
}
public static void quickSort(int[] nums, int left, int right){
if (left >= right){ // 若当前左边界大于等于右边界则结束递归
return;
}
int p = helper(nums, left, right); // 分区位置
quickSort(nums, left, p - 1); // 左侧分区
quickSort(nums, p + 1, right); // 右侧分区
}
public static int helper(int[] nums, int left, int right){
int low = left; // 设置快慢指针
int quick = left;
int target = nums[right]; // 设置基准元素为右边界值,为了防止最坏情况,更可以用随机数组元素值。
while (quick < right){
if (quick < right && nums[quick] > target){ // 若快指针元素大于基准元素则快指针右移
quick++;
}
if (quick < right && nums[quick] <= target){ // 若快指针元素小于等于基准元素则交换快慢指针元素,并将快慢指针同时右移
swap(nums, low, quick);
quick++;
low++;
}
}
swap(nums, low, quick); // 循环结束交换快慢指针元素
return low; // 返回分区位置
}
public static void swap(int[] nums, int left, int right){
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
以上代码是自己编写,代码较差有优化空间请见谅。请大佬们见谅!
浙公网安备 33010602011771号