当前位置:   article > 正文

【归并排序/快排/堆排序】912. 排序数组

【归并排序/快排/堆排序】912. 排序数组

力扣连接:. - 力扣(LeetCode)

归并排序

对左右子集合分别排序,然后合并两个有序数组

  1. class Solution {
  2. int[] nums;
  3. public int[] sortArray(int[] nums) {
  4. this.nums = nums;
  5. return sort(0, nums.length-1);
  6. }
  7. int[] sort(int st, int ed) {
  8. if(st == ed) {
  9. return new int[]{nums[st]};
  10. }
  11. //对左右分别排序
  12. int m = st + (ed-st)/2;
  13. int[] leftArr = sort(st, m);
  14. int[] rightArr = sort(m+1, ed);
  15. //合并两个有序数组
  16. int[] newArr = new int[ed-st+1];
  17. int i=0,j=0,k=0;
  18. while(i<leftArr.length && j<rightArr.length){
  19. if(leftArr[i]<rightArr[j]){
  20. newArr[k++]=leftArr[i++];
  21. }else{
  22. newArr[k++]=rightArr[j++];
  23. }
  24. }
  25. while(i<leftArr.length) newArr[k++] = leftArr[i++];
  26. while(j<rightArr.length) newArr[k++] = rightArr[j++];
  27. return newArr;
  28. }
  29. }

快排

每次任意指定一个数作为标杆,小于标杆的放左边,大于标杆的放右边,对左右子数组重复这个流程

时间复杂度:O(n log n)

空间复杂度:O(n)

  1. class Solution {
  2. int[] nums;
  3. public int[] sortArray(int[] nums) {
  4. this.nums = nums;
  5. sort(0, nums.length - 1);
  6. return nums;
  7. }
  8. void sort(int st, int ed) {
  9. if (st >= ed)
  10. return;
  11. int p = st, l = st, r = ed;
  12. while (l < r) {
  13. // r指向第一个小于等于nums[p]的,注意这和下个while顺序不能随便换,要保证l和r最后指向小于等于nums[p]的地方
  14. while (l < r && nums[r] > nums[p]) r--;
  15. // l指向第一个大于nums[p]的
  16. while (l < r && nums[l] <= nums[p]) l++;
  17. swap(l, r);
  18. }
  19. swap(p, l);
  20. sort(st, l - 1);
  21. sort(l + 1, ed);
  22. }
  23. void swap(int i, int j) {
  24. int temp = nums[i];
  25. nums[i] = nums[j];
  26. nums[j] = temp;
  27. }
  28. }

堆排序

时间复杂度:O(nlogn)

视频讲解:排序算法:堆排序【图解+代码】_哔哩哔哩_bilibili

大顶堆:父节点比两个子节点都要大

下标规律:

节点 i 的父节点:(i-1)/2

节点 i 的左子节点:i*2+1

节点i的右子节点:(i+1)*2

维护大顶堆:从下往上,第一个有孩子节点的节点开始,取根节点、左孩子、右孩子之间的最大值 换到根节点处

排序:堆顶的元素一定是最大的,每次将堆顶元素放到尾部,然后剩下元素再次维护大顶堆,重复

  1. class Solution {
  2. int[] nums;
  3. public int[] sortArray(int[] nums) {
  4. this.nums = nums;
  5. int len = nums.length;
  6. sort(len);
  7. return nums;
  8. }
  9. void sort(int len) {
  10. //建堆
  11. for(int i= len/2-1;i>=0;i--) {
  12. heapify(len, i);
  13. }
  14. //排序
  15. for(int i=len-1;i>0;i--) {
  16. swap(i, 0);
  17. //i以后的数是已经排序好的
  18. heapify(i, 0);
  19. }
  20. }
  21. //i: 待维护的节点下标
  22. //len: 参与维护大顶堆的数组长度
  23. void heapify(int len, int i) {
  24. int biggest = i;
  25. int left = i*2+1;
  26. int right = (i+1)*2;
  27. //len用来约束递归终止条件
  28. if(left<len && nums[biggest]<nums[left]){
  29. biggest = left;
  30. }
  31. if(right<len && nums[biggest]<nums[right]){
  32. biggest = right;
  33. }
  34. if(biggest != i){
  35. swap(biggest, i);
  36. heapify(len, biggest);
  37. }
  38. }
  39. void swap(int i, int j) {
  40. int temp = nums[i];
  41. nums[i] = nums[j];
  42. nums[j] = temp;
  43. }
  44. }

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

闽ICP备14008679号