热门标签 | 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);}
};

欢迎大家在评论区交流~


推荐阅读
  • 本文将继续探讨 JavaScript 函数式编程的高级技巧及其实际应用。通过一个具体的寻路算法示例,我们将深入分析如何利用函数式编程的思想解决复杂问题。示例中,节点之间的连线代表路径,连线上的数字表示两点间的距离。我们将详细讲解如何通过递归和高阶函数等技术实现高效的寻路算法。 ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 双指针法在链表问题中应用广泛,能够高效解决多种经典问题,如合并两个有序链表、合并多个有序链表、查找倒数第k个节点等。本文将详细介绍这些应用场景及其解决方案。 ... [详细]
  • 深入理解排序算法:集合 1(编程语言中的高效排序工具) ... [详细]
  • 普通树(每个节点可以有任意数量的子节点)级序遍历 ... [详细]
  • 三角测量计算三维坐标的代码_双目三维重建——层次化重建思考
    双目三维重建——层次化重建思考FesianXu2020.7.22atANTFINANCIALintern前言本文是笔者阅读[1]第10章内容的笔记,本文从宏观的角度阐 ... [详细]
  • 本文介绍了几种常用的图像相似度对比方法,包括直方图方法、图像模板匹配、PSNR峰值信噪比、SSIM结构相似性和感知哈希算法。每种方法都有其优缺点,适用于不同的应用场景。 ... [详细]
  • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
  • 在使用 Cacti 进行监控时,发现已运行的转码机未产生流量,导致 Cacti 监控界面显示该转码机处于宕机状态。进一步检查 Cacti 日志,发现数据库中存在 SQL 查询失败的问题,错误代码为 145。此问题可能是由于数据库表损坏或索引失效所致,建议对相关表进行修复操作以恢复监控功能。 ... [详细]
  • 泰波那契数列与斐波那契数列类似,但其计算方法有所不同。本文详细解析了如何高效计算第 N 个泰波那契数,并提供了一种基于动态规划的优化算法。通过使用数组记录中间结果,避免了重复计算,显著提高了算法的执行效率。代码示例展示了具体的实现方法,帮助读者更好地理解和应用这一算法。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 自然语言处理(NLP)——LDA模型:对电商购物评论进行情感分析
    目录一、2020数学建模美赛C题简介需求评价内容提供数据二、解题思路三、LDA简介四、代码实现1.数据预处理1.1剔除无用信息1.1.1剔除掉不需要的列1.1.2找出无效评论并剔除 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 本文提出了一种基于栈结构的高效四则运算表达式求值方法。该方法能够处理包含加、减、乘、除运算符以及十进制整数和小括号的算术表达式。通过定义和实现栈的基本操作,如入栈、出栈和判空等,算法能够准确地解析并计算输入的表达式,最终输出其计算结果。此方法不仅提高了计算效率,还增强了对复杂表达式的处理能力。 ... [详细]
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社区 版权所有