热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

剑指offer53.数组中的逆序对

✍个人博客:https:blog.csdn.netNewin2020?spm1011.2415.3001.5343📚专栏地址:剑指off

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:剑指offer系列题解
📝原题地址:题目地址
📣专栏定位:为找工作的小伙伴整理常考算法题解,祝大家都能成功上岸!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪



题目描述


在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。

输入一个数组,求出这个数组中的逆序对的总数。

数据范围

给定数组的长度 [0,100]。

样例

输入:[1,2,3,4,5,6,0]输出:6


方法一:归并排序 O(nlogn)

我们可以在进行归并排序的过程中,计算逆序对的个数。
ns
归并排序每趟排序都是对已知的两个有序的序列进行排序,我们可以在排序过程中,利用该排序的特性进行逆序对的计算。我们举个例子,看看具体步骤是如何实现的:

假设我们已经进行到了归并排序中最后一趟合并,通过之前的递归调用,已经得到了两个有序的序列,分别是数组的前后两半部分。然后我们初始化两个指针 ij ,使他们分别指向数组前半部分和数组后半部分的第一个元素。

在这里插入图片描述

第一步&#xff1a; 判断两指针指向的元素&#xff0c;发现 nums[i] 1 <2 。此时 i 指向的元素要小于 j 指向的元素&#xff0c;所以不用计算逆序对&#xff0c;直接加入答案数组中即可。

因为 i 指向的这个元素始终是在 j 指向的元素左边&#xff0c;即使排不排序都不会改变两者的相对位置即无法构成一个逆序对。另外&#xff0c;左半部分 1 以后的元素都大于等于 1 &#xff0c;故无法判断它们与 2 之间的关系&#xff0c;逆序对不能计算。

在这里插入图片描述

第二步&#xff1a; 判断两指针指向的元素&#xff0c;发现 nums[i] > nums[j]4 > 2 。此时就要注意了&#xff0c;因为执行完排序后&#xff0c;42 的相对位置会发生改变&#xff0c;说明 42 排序前就可以构成逆序对。

另外&#xff0c;由于左半部分数组与右半部分数组只是在各个区间内有序&#xff0c;两部分区间中的元素之间的相对位置并没有发生改变。

所以左半部分中 4 以后的元素 58 都一定是大于 2 的&#xff0c;并且他们在排序之前都是可以构成逆序对的&#xff0c;故可以得到 &#96;res &#43;&#61; mid - i &#43; 1 &#61; 3 - 1 &#43; 1 &#61; 3 。

在这里插入图片描述

第三步&#xff1a; 与第二步一样&#xff0c; nums[i] > nums[j]4 > 3 。所以 4 后面的 58 同样都大于 3 &#xff0c;他们之间同样可以构成逆序对&#xff0c;故 res &#43;&#61; 3

在这里插入图片描述

第四步&#xff1a; 与第一步一样&#xff0c;nums[i] 4 <6 &#xff0c;故直接加入答案数组中即可。

在这里插入图片描述

第五步&#xff1a; 同样&#xff0c;nums[i] 5 <6 &#xff0c;故直接加入答案数组中即可。

在这里插入图片描述

第七步&#xff1a; nums[i] > nums[j]8 > 68 后面没有元素了&#xff0c;故 res &#43;&#61; 1
在这里插入图片描述

第八步&#xff1a; nums[i] 8 <9 &#xff0c;故直接加入答案数组中即可。

在这里插入图片描述

第九步&#xff1a; 左半数组已经全部遍历完&#xff0c;故直接将右半数组的剩余部分加入答案数组中&#xff0c;并返回最终计算的逆序对数量 res 即可。

在这里插入图片描述


Tips&#xff1a; 可能会有小伙伴担心其中计算的逆序对会不会有重复的部分&#xff0c;其实完全不会。因为归并排序每趟排序中用到的两个数组部分的相对位置都还没有进行改变&#xff0c;每次计算出来的逆序对一定是唯一的。


class Solution {
public://归并排序的过程中计算逆序对个数int merge(vector<int>& nums, int l, int r) {if (l >&#61; r) return 0;int mid &#61; l &#43; r >> 1;int res &#61; merge(nums, l, mid) &#43; merge(nums, mid &#43; 1, r);vector<int> temp;int i &#61; l, j &#61; mid &#43; 1;while (i <&#61; mid && j <&#61; r)if (nums[i] <&#61; nums[j]) temp.push_back(nums[i&#43;&#43;]);else {temp.push_back(nums[j&#43;&#43;]);res &#43;&#61; mid - i &#43; 1;}while (i <&#61; mid) temp.push_back(nums[i&#43;&#43;]);while (j <&#61; r) temp.push_back(nums[j&#43;&#43;]);int k &#61; l;for (auto x : temp) nums[k&#43;&#43;] &#61; x;return res;}int inversePairs(vector<int>& nums) {return merge(nums, 0, nums.size() - 1);}
};

欢迎大家在评论区交流~


推荐阅读
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • 文章目录题目:二叉搜索树中的两个节点被错误地交换。基本思想1:中序遍历题目:二叉搜索树中的两个节点被错误地交换。请在不改变其结构的情况下 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文介绍了如何使用MATLAB调用摄像头进行人脸检测和识别。首先需要安装扩展工具,并下载安装OS Generic Video Interface。然后使用MATLAB的机器视觉工具箱中的VJ算法进行人脸检测,可以直接调用CascadeObjectDetector函数进行检测。同时还介绍了如何调用摄像头进行人脸识别,并对每一帧图像进行识别。最后,给出了一些相关的参考资料和实例。 ... [详细]
  • Parity game(poj1733)题解及思路分析
    本文是对题目"Parity game(poj1733)"的解题思路进行分析。题目要求判断每次给出的区间内1的个数是否和之前的询问相冲突,如果冲突则结束。本文首先介绍了离线算法的思路,然后详细解释了带权并查集的基本操作。同时,本文还对异或运算进行了学习,并给出了具体的操作步骤。最后,本文给出了完整的代码实现,并进行了测试。 ... [详细]
author-avatar
手机用户2502914373
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有