冒泡排序的交换次数

Posted 普通网友

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冒泡排序的交换次数相关的知识,希望对你有一定的参考价值。

题意:

给定一个1~n的排列a0,a1,…an-1,求对这个数列进行冒泡排序所需要的交换次数(冒泡排序是每次找到满足ai>ai+1的i,并交换ai和ai+1,直到这样的i不存在为止的算法)。

限制条件:1<= n<= 100000

 

输入:

n=4, a=3,1,4,2

输出:

3

 

冒泡排序的复杂度是O(n2),所有无法通过模拟冒泡排序的过程来计算需要的交换次数。不过我们可以通过选取适当的数据结构来解决这个问题。

首先,所求的交换次数等价于满足i<j,ai>aj的(i,j)数对的个数(这种数对的个数叫做逆序数)。而对于每一个j,如果能够快速求出满足i<j,ai>aj的i的个数,那么问题就迎刃而解。我们构建一个值得范围是1~n的BIT,按照j=0,1,2,…,n-1的顺序进行如下操作。

*把j-(BIT查询得到的前aj项的和)加到答案中

*把BIT中aj位置上的值加1

对于每一个j,(BIT查询得到的前aj项的和)就是满足i<j,ai<=aj的i的个数。因此把这个值从j中减去之后,得到的就是满足i<j,ai>aj的i的个数。由于对于每一个j的复杂度是O(logn),所以整个算法的复杂度是O(nlogn)。

#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 100000 + 10;

int n;
int a[maxn];
int bit[maxn];

int sum(int i)

    int s = 0;
    while (i > 0)
        s += bit[i];
        i -= i & -i;
    
    return s;


void add(int i, int x)

    while (i <= n)
        bit[i] += x;
        i += i & -i;
    


void solve()

    ll ans = 0;
    for (int j = 0; j < n; j++)
        ans += j - sum(a[j]);
        add(a[j], 1);
    
    printf("%lld\\n", ans);

int main()

    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    
    solve();
    return 0;



以上是关于冒泡排序的交换次数的主要内容,如果未能解决你的问题,请参考以下文章

冒泡排序中的交换次数

冒泡排序的交换次数 (树状数组)

冒泡排序中数据交换的次数

冒泡排序

排序算法系列1--简单排序(选择,冒泡,直接插入)

1,2,3,4,5,6,7最小比较和交换次数的排序次序为?