左神算法讲堂笔记 01 归并排序和应用 --- 小和问题、逆序数

1、master公式求递归的时间复杂度

T(N) = a*T(N/b) + O(N^d)

  1. log(b,a) > d -> 复杂度为O(N^log(b,a))
  2. log(b,a) = d -> 复杂度为O(N^d * logN)
  3. log(b,a) < d -> 复杂度为O(N^d)

2、归并排序(合并的时候,相等值那么左边先放,就能实现稳定性)

第一步:左边整体有序
第二步:右边整体有序
第三步:左右整合成完全有序(耗费空间o(n))

时间复杂度根据master公式求得 T(n) = 2 * T(n/2) + o(n) = o(N * logN )

3、小和问题

在这里插入图片描述

解法:

利用归并排序,维护左右部分有序,用下标p1遍历左部分,p2遍历右部分。
在整合左右部分为有序时,可以进行小和的计算。
当arr[ p1 ] < arr[ p2 ] 时,此时产生的小和数为 arr[ p1 ] * ( r - p2 + 1) 。然后把arr [ p1 ]放到帮助数组中, p1++。
否则直接把arr[ p2 ] 放到帮助数组, p2++;

 public int smallSum(int[] arr) {
        if(arr == null || arr.length < 2)
            return 0
        return merge(arr, 0, arr.length - 1);
    }

    public int merge(int[] arr, int l, int r) {
       if(l == r)
           return 0;
        int mid = ((l+r)>>1);
        return merge(arr, l, mid) +merge(arr, mid + 1, r)+ exchange(arr,l,r);
    }

    int exchange(int[] arr, int l, int r) {
        int mid = ((l+r)>>1);
        int p1 = l, p2 = mid+1;
        int arr2[] = new int[r-l+1];
        int index = 0;
        int tmp = 0;
        while (p1 <= mid && p2 <= r) {
            if (arr[p1] < arr[p2]) {
                //右边大
                tmp += arr[p1] * (r - p2 + 1);
                arr2[index++] = arr[p1++];
            }else
                arr2[index++] = arr[p2++];
        }
        while (p1<=mid){
            arr2[index++] = arr[p1++];
        }
        while (p2<=r){
            arr2[index++] = arr[p2++];
        }
        index = 0;
        while (l<=r){
            arr[l++] = arr2[index++];
        }
        return tmp;
    }

4、逆序数问题

求和过程中,当 arr[ p1 ] > arr[ p2 ],res += mid-p1+1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值