分而治之:逆序对计数问题

分而治之:逆序对计数问题

问题:
输入一个长度长度为n的数组A[n],求出数组A[n]逆序对的总数。
输入:
长度为n的数组A[n]
输出:
数组A[n]逆序对的总数

问题分析:

在这里插入图片描述

  1. 把数组A二分为两个子数组A[1…n/2],A[n/2 + 1…n]
  2. 递归求解子问题
    求解S1∶仅在A[1…n/2]中的逆序对数目
    求解S2∶仅在A[n/2+1…n]中的逆序对数目
  3. 合并A[1…n/2]和A[n/2 +1…n]的解
    求解S3∶跨越子数组的逆序对数目
    S = S1+S2+S3

与最大子数组的问题一样,执行效率的瓶颈值也在合并方面,也就是S3跨越子数组的逆序对数目的求解问题。

S3的求解:

1. 策略一:直接求解
(1)对每个Aj]∈ A[m +1…n],枚举A[i]∈ A[1…m]并统计逆序对数目
(2)求解S的算法运行时间:O(n2)
在这里插入图片描述
直接求解的运行时间不是很理想,所以,有没有更好的方法呢?

2. 策略二:排序求解
(1)分别对数组A[1…m]和A[m+ 1…n]进行排序
(2)对于每个A[ j ]∈A[m+1…n],采用二分查找为其在A[1…m]中定位;
(3)A[ j ]在A[1…m]定位点右侧的元素均可与A[ j ]构成逆序对;
(4)求解S的算法运行时间:O(nlogn)。
在这里插入图片描述

排序求解S的分而治之提高了算法运行时间,但仍然还有优化的可能;

3. 策略三:归并求解
(1)从左到右扫描有序子数组:A[i]∈A[1…m],A[j] ∈ A[m+1…n]
···如果A[i] > A[j],统计逆序对,j向右移
···如果A[i] ≤ A[j],i向右移
(2)利用归并排序框架保证合并后数组的有序性
(3)S时间复杂度降至O(n)
在这里插入图片描述

算法分析图:

在这里插入图片描述

代码

#include <iostream>
#include <cstdio>
using namespace std;

const int N = 10000;
int a[N],b[N];
int count;

void Merge(int a[], int l, int mid , int r)  //归并排序的合并部分
{
   
	int i = l, j = mid + 1,k = l;
	
	//遍历统计逆序数对
	while(i 
  • 8
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值