求数组的逆序对(百度笔试题)

多人排成一个队列,我们认为从低到高是正确的序列,但是总有部分人不遵守秩序。如果说,前面的人比后面的人高(两人身高一样认为是合适的),那么我们就认为这两个人是一对“捣乱分子”,比如说,现在存在一个序列:

176,   178,   180,   170,   171

这些捣乱分子对为 <176,   170 >,   <176,   171 >,   <178,   170 >,   <178,   171 >,   <180,   170 >,   <180,   171 >,  

那么,现在给出一个整型序列,请找出这些捣乱分子对的个数(仅给出捣乱分子对的数目即可,不用具体的对)

 

    要求:

输入:

为一个文件(in),文件的每一行为一个序列。序列全为数字,数字间用”,”分隔。

输出:

为一个文件(out),每行为一个数字,表示捣乱分子的对数。

 

详细说明自己的解题思路,说明自己实现的一些关键点。并给出实现的代码   ,并分析时间复杂度。

 

限制:

输入每行的最大数字个数为100000个,数字最长为6位。程序无内存使用限制。

 

解:此题的意思就是统计一个数组中的逆序对的个数为多少。根据归并排序算法的思想,可以对这个问题进行一下归并排序。然后就能统计出逆序对的个数。例如有16个数的数组,则进行归并排序的算法过程如下:

01)(23)(03)(45)(67)(47)(07)(89)(1011)(811)(1213)(1415)(1215)(815)(015

其中(01)表示数组中第0个数和第1个数进行合并。

代码如下:

/*

 * 24_inversion.c

 * Count inversions using merge sorting.

 *

 * Author: Yundeng Pan

 * Date:   2009-7-11

 * Email:  intrepyd@gmail.om

 * Blog:   http://blog.csdn.net/intrepyd

 */

 

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

 

#define ARRAY_LENGTH 16

 

 

int merge_inversions(int *array, int p, int q, int r)

{

    int n1, n2, i, j, k, count=0;

    int *left=NULL, *right=NULL;

 

    n1 = q-p+1;

    n2 = r-q;

 

    left = (int *)malloc(sizeof(int)*(n1));

    right = (int *)malloc(sizeof(int)*(n2));

    for(i=0; i<n1; i++)

    {

                   left[i] = array[p+i];

    }

    for(j=0; j<n2; j++)

    {

                   right[j] = array[q+1+j];

    }

 

           i = j = 0;

           k = p;

    while(i<n1 && j<n2)

    {

                   if(left[i] <= right[j])

                   {

                            array[k++] = left[i++];

                   }

                   else

                   {

                            count += n1 - i;

                            array[k++] = right[j++];

                   }

    }

 

    for(; i<n1; i++)

    {

                   array[k++] = left[i];

    }

    for(; j<n2; j++)

    {

                   array[k++] = right[j];

    }

 

                   free(left);

                   free(right);

                   left = NULL;

                   right = NULL;

 

                   return count;

}

 

int count_inversions(int *array, int p, int r)

{

    int q, count=0;

 

    if(p < r)

    {

                   q = (int)((p+r)/2);

                   count += count_inversions(array, p, q);

                   count += count_inversions(array, q+1, r);

                   count += merge_inversions(array, p, q, r);

    }

    return count;

}

 

int main()

{

    int i, count, array[ARRAY_LENGTH];

 

    printf("/nOriginal array:/n");

    srand(time(NULL));

    for(i=0; i<ARRAY_LENGTH; i++)

    {

                   array[i] = rand() % 20;

                   printf("%d  ", array[i]);

         }   

 

    count = count_inversions(array, 0, ARRAY_LENGTH-1);

    printf("/n/nNumber of inversions is: %d/n/n", count);

 

    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值