zoukankan      html  css  js  c++  java
  • 归并排序之求小和

    小和问题
    在一个数组中, 每一个数左边比当前数小的数累加起来, 叫做这个数组的小和。 求一个数组
    的小和。
    例子:
    [1,3,4,2,5]
    1左边比1小的数, 没有;
    3左边比3小的数, 1;
    4左边比4小的数, 1、 3;
    2左边比2小的数, 1;
    5左边比5小的数, 1、 3、 4、 2;
    所以小和为1+1+3+1+1+3+4+2=16


    如果直接用两层for循环扫一遍,时间复杂度O(n*n),这个题目可以利用归并排序把时间复杂度降到O(nlogn)
     

     1 package com.sort.demo;
     2 
     3 public class Mergesort extends Sort {
     4 
     5     @Override
     6     public void sort(int[] arr) {
     7         if (arr == null || arr.length < 2)
     8             return;
     9         processSort(arr, 0, arr.length - 1);
    10     }
    11 
    12     public void processSort(int[] arr, int L, int R) {
    13         if (L == R)
    14             return;
    15         int mid = (L + R) / 2;
    16         //左边排序
    17         processSort(arr, L, mid);
    18         //右边排序
    19         processSort(arr, mid + 1, R);
    20         merge(arr, L, mid, R);
    21     }
    22 
    23     public void merge(int[] arr, int L, int mid, int R) {
    24 
    25         if (arr == null || arr.length < 2)
    26             return;
    27         int[] help = new int[R - L + 1];
    28         int i = 0;
    29         int p1 = L;
    30         int p2 = mid + 1;
    31         //左右两边的有序数组都不越界
    32         while (p1 <= mid && p2 <= R) {
    33             help[i++] = arr[p1] > arr[p2] ? arr[p2++] : arr[p1++];
    34         }
    35         //右边越界,左边依次copy到结果数组
    36         while (p1 <= mid) {
    37             help[i++] = arr[p1++];
    38         }
    39 //        左边越界,右边依次copy到结果数组
    40         while (p2 <= R) {
    41             help[i++] = arr[p2++];
    42         }
    43         //再copy回原数组
    44         for (i = 0; i < help.length; i++) {
    45 //            很容易出错的地址,这个地方应该是L+i,而不是i,因为从arr的L到R合并
    46             arr[L + i] = help[i];
    47         }
    48     }
    49 
    50     public static void main(String[] args) {
    51         int[] arr = new int[]{1, 3, 4, 2, 5};
    52         SmallSum smallSum = new SmallSum();
    53         smallSum.sort(arr);
    54     }
    55 
    56     //使用归并排序做小和
    57     static class SmallSum extends Sort {
    58 
    59         @Override
    60         public void sort(int[] arr) {
    61             if (arr == null || arr.length < 2)
    62                 return;
    63             int sum = 0;
    64             sum += mergeSort(arr, 0, arr.length - 1);
    65             System.out.println(sum);
    66         }
    67 
    68 
    69         private int mergeSort(int[] arr, int L, int R) {
    70             if (L == R)
    71                 return 0;
    72             int mid = L + ((R - L) >> 1);
    73             return mergeSort(arr, L, mid) + mergeSort(arr, mid + 1, R) + merge(arr, L, mid, R);
    74         }
    75 
    76         private int merge(int[] arr, int L, int mid, int R) {
    77             int res = 0;
    78             int p1 = L;
    79             int p2 = mid + 1;
    80             int i = 0;
    81             int[] help = new int[R - L + 1];
    82             while (p1 <= mid && p2 <= R) {
    83                 res += arr[p1] < arr[p2] ? (R - p2 + 1) * arr[p1] : 0;
    84                 help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
    85             }
    86             while (p1 <= mid) {
    87                 help[i++] = arr[p1++];
    88             }
    89             while (p2 <= R) {
    90                 help[i++] = arr[p2++];
    91             }
    92             for (i = 0; i < help.length; i++) {
    93                 arr[L + i] = help[i];
    94             }
    95             return res;
    96         }
    97     }
    98 }
    求小和
  • 相关阅读:
    团队项目 第一次作业
    20165201 课下作业第十周(选做)
    20165201 实验三敏捷开发与XP实践
    20165201 2017-2018-2 《Java程序设计》第9周学习总结
    20165201 结对编程练习_四则运算(第二周)
    20165201 2017-2018-2 《Java程序设计》第8周学习总结
    20165201 实验二面向对象程序设计
    20165326 java实验五
    20165326 课程总结
    20165326 java实验四
  • 原文地址:https://www.cnblogs.com/zqr99/p/11849716.html
Copyright © 2011-2022 走看看