归并排序应用——剑指 Offer 51. 数组中的逆序对

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了归并排序应用——剑指 Offer 51. 数组中的逆序对相关的知识,希望对你有一定的参考价值。

(文章目录)

题目

1.错误示范


int reversePairs(int* nums, int numsSize) 
    int i = 0;
    int j = 0;
    int sum = 0;
    for (i = 0; i < numsSize; i++)
    
        for (j = i + 1; j < numsSize; j++)
        
            if (nums[i] > nums[j])
            
                sum++;
            
        
    
    return sum;

2. 分析

逆序对的判断

统计出某个数后面有多少个数比它小

举例(完整过程解析)

第一次循环

第二次循环

第三次循环

第四次循环

第五次循环

循环结束的两种存在情况

<font color=red> 由于right数组已经遍历完,所以循环停止,再次判断两个数组是否存在数</font>

3. 正确代码


int mergesort1(int* nums, int left, int right, int* tmp)//归并排序

    if (left >= right)
    
        return  0;
    
    int mid = (left + right) / 2;
    int leftret = mergesort1(nums, left, mid, tmp);//计算左边区间 [left, mid] 中逆序对的数量 = leftRet,并排序;
    int rightret = mergesort1(nums, mid + 1, right, tmp);//. 计算右边区间 [mid + 1, right] 中逆序对的数量 = rightRet,并排序
    int begin1 = left;
    int end1 = mid;
    int begin2 = mid + 1;
    int end2 = right;
    int i = left;
    int voeret = 0;//合并左右两个有序区间,并且计算逆序对的数量
    while (begin1 <= end1 && begin2 <= end2)
    
        if (nums[begin1] <= nums[begin2])
        
            //当 nums[begin1] <= nums[begin2] 时,说明此时右边数组已经遍历过的元素都是比
           // nums[begin1] 小的,因此累加到 voeret 中去
            voeret += begin2 - (mid + 1);//因为计算的begin2刚开始的边界就为 mid+1
            tmp[i++] = nums[begin1++];
        
        else
        
            //当 nums[begin1] > nums[begin2] 时,无需统计,直接归并
            tmp[i++] = nums[begin2++];
        
    
    //处理归并排序中剩余的元素;
    //当左边有剩余的时候,还需要统计逆序对的数量;
        //当右边还有剩余的时候,无需统计,直接归并。
    while (begin1 <= end1)
    
        voeret += begin2 - (mid + 1);
        tmp[i++] = nums[begin1++];
    
    while (begin2 <= end2)
    
        tmp[i++] = nums[begin2++];
    
    memcpy(nums + left, tmp + left, sizeof(int) * (right - left + 1));
    return leftret + rightret + voeret;//返回 左区间逆序对数量 + 右区间逆序对数量 + 当前合并过程中产生的逆序对数量

int  mergesort(int* nums, int numsSize)

    int* tmp = (int*)malloc(sizeof(int) * numsSize);//因为我们不想一直malloc创建数组所以在外面开辟
    int ret = mergesort1(nums, 0, numsSize - 1, tmp);
    free(tmp);
    tmp = NULL;
    return ret;

int reversePairs(int* nums, int numsSize) 
    return mergesort(nums, numsSize);


4.递归展开图

以上是关于归并排序应用——剑指 Offer 51. 数组中的逆序对的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer 51. 数组中的逆序对(归并排序,Java)

剑指 Offer 51. 数组中的逆序对(归并排序,Java)

结合《剑指offer(第二版)》面试题51来谈谈归并排序

剑指 Offer 51. 数组中的逆序对

剑指offer(51)

剑指Offer对答如流系列 - 数组中的逆序对