当前位置:   article > 正文

排序思想-快排

排序思想-快排

快速排序

912.排序数组 

快速排序核心思想就是每次在当前区间 [left, right] 中选择出一个元素 nums[p],然后将区间内所有大于它的元素和所有小于它的元素都放到其两侧【具体放在哪一侧取决于是升序还是降序】,然后再递归去处理两侧区间。

  1. class Solution {
  2. public int[] sortArray(int[] nums) {
  3. quickSort2(nums,0,nums.length-1);
  4. return nums;
  5. }
  6. // 荷兰国旗问题
  7. public static int first, last;
  8. public static void quickSort2(int[] arr, int l, int r) {
  9. if(l>=r) return;
  10. // 随机这一下,常数时间比较大
  11. // 但只有这一下随机,才能在概率上把快速排序的时间复杂度收敛到O(n * logn)
  12. int x = arr[l + (int) (Math.random() * (r - l + 1))];
  13. partition2(arr, l, r, x);
  14. // 为了防止底层的递归过程覆盖全局变量
  15. // 这里用临时变量记录firstlast
  16. int left = first;
  17. int right = last;
  18. quickSort2(arr, l, left - 1);
  19. quickSort2(arr, right + 1, r);
  20. }
  21. // 已知arr[l....r]范围上一定有x这个值
  22. // 划分数组 <x放左边,==x放中间,>x放右边
  23. // 把全局变量first, last,更新成==x区域的左右边界
  24. public static void partition2(int[] arr, int l, int r, int x) {
  25. first = l;
  26. last = r;
  27. int i = l;
  28. while (i <= last) {
  29. if (arr[i] == x) {
  30. i++;
  31. } else if (arr[i] < x) {
  32. swap(arr, first++, i++);
  33. } else {
  34. swap(arr, i, last--);
  35. }
  36. }
  37. }
  38. public static void swap(int[] nums, int i, int j){
  39. if(i==j) return;
  40. nums[i] ^= nums[j];
  41. nums[j] ^= nums[i];
  42. nums[i] ^= nums[j];
  43. }
  44. }

双指针交换的方式划分左右区间

215.数组中第K个最大元素.

将大于切分值的元素都放到左侧,小于切分值得元素都放到右侧。因此我们可以使用双指针分别从两端往中间搜索,分别找到左侧小于切分值的元素和右侧大于切分值的元素,交换之,直到两个指针相遇。

对于这道题,我们可以选择区间的中间值作为切分元素,并且我们要事先将切分值交换到区间的右边界:

  1. 避免在划分左右区间的时候,将切分值给覆盖掉。
  2. 最终才可以将切分值放到正确的位置。
  1. class Solution {
  2. public int findKthLargest(int[] nums, int k) {
  3. return quickSortKth(nums,k,0,nums.length-1);
  4. }
  5. private int quickSortKth(int[] nums, int k, int left, int right){
  6. int mid =left + (right-left) / 2;
  7. swap(nums,mid, right); // 将切分值放到右边界避免加入元素的划分
  8. int partition = nums[right], i=left, j=right; // 双指针从左右边界开始,分别找到要交换的元素
  9. while(i<j){
  10. while(i<j && nums[i]>=partition) i++;
  11. while(j>i && nums[j]<=partition) j--; // 找到右侧大于切分值的元素【因为是找大于,即使j从right开始,right也不会被选中】
  12. swap(nums,i,j);
  13. }
  14. swap(nums,i,right); // i最后停留的位置一定是右侧首个小于切分值的元素,与切分值交换,则[left, i)都是大于(等于)切分值,[i+1, right]都是小于(等于)切分值
  15. if(i==k-1) return nums[i];
  16. if(i<k-1) return quickSortKth(nums,k,i+1,right);
  17. return quickSortKth(nums,k,left,i-1);
  18. }
  19. private void swap(int[] nums, int i, int j){
  20. if(i == j) return;
  21. nums[i] ^= nums[j];
  22. nums[j] ^= nums[i];
  23. nums[i] ^= nums[j];
  24. }
  25. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/846026
推荐阅读
相关标签
  

闽ICP备14008679号