7.23 不能一次写出来,明天再写一次!
    7.24 不能一次 AC,明天再写一次!
    7.25 不能一次 AC,差一点点
    7.28 一次 AC
    归并排序 - 图1
    7.24 出错心得:
    **

    • 14行和15行:“分”的时候只需要左右区间就可以分,不需要 mid;“治”的时候才需要传 mid 进去。

    • 28行与34行 for 循环中第二部分的判断条件要为:k <= h 才行!!!一定要有等于 h !因为 h 是当前数组的右边界的索引!是包括数组的数值的!要算进去!

    • 35行和36行中的条件判断为:i > m 与 j > h + 1 或者 i == m + 1 与 j == h + 1 都行!

    • 37行和38行中:对应左区间或者右区间元素放入原数组后,其索引要记得加一i++ 与 j++ 后面的 ++ 要记得写上去

    • 第37行,要记得用辅助数组 tmp 中的值去比较!!

      1. class Solution {
      2. int[] tmp; // 归并排序最重要的是要有个辅助数组要存储 “治” 之前的数据
      3. public int[] sortArray(int[] nums) {
      4. tmp = new int[nums.length]; // 辅助数组长度要和原数组一致
      5. mergeSort(nums, 0, nums.length - 1);
      6. return nums;
      7. }
      8. public void mergeSort(int[] nums, int l, int h) {
      9. if(l >= h) return; // 当分到只剩一个数据时就不用再分了
      10. int m = (l + h) / 2; // m: mid属于左边
      11. mergeSort(nums, l, m); // 向下递归:分左边
      12. mergeSort(nums, m + 1, h);// 向下递归:分右边
      13. merge(nums, l, m, h); // 向上回溯:归并 [l,m] 与 [m+1,h]
      14. }
      15. // 原地归并方法
      16. public void merge(int[] nums, int l, int m, int h) {
      17. // 归并排序实际改变的是原数组!
      18. // 但是归并的时候得通过判断原数组的大小来交换数据;
      19. // 所以在正式交换之前得把原数组数据复制到辅助数组中;
      20. // 辅助数组保存着还没交换前的数组的状态!
      21. // 我们就可以通过辅助数组来判断大小关系;
      22. // 交换数据的源也是从辅助数组中来,以达到修改原数组的目的!
      23. for(int k = l; k <= h; k++) {
      24. tmp[k] = nums[k];
      25. }
      26. int i = l, j = m + 1;
      27. for(int k = l; k <= h; k++) {
      28. if(i > m) nums[k] = tmp[j++]; // i 越界:左区间比完,将右区间剩余数据直接覆盖到原数组
      29. else if(j > h) nums[k] = tmp[i++]; // j 越界:右区间比完,将左区间剩余数据直接覆盖到原数组
      30. else if(tmp[i] <= tmp[j]) nums[k] = tmp[i++]; // 左比右小(等于也行),左进入原数组对应位置
      31. else nums[k] = tmp[j++]; // 右比左小,右进入原数组对应位置
      32. }
      33. }
      34. }