剑指offer-35、数组中的逆序对

news/2025/10/16 9:07:18/文章来源:https://www.cnblogs.com/sevencoding/p/19137145

题⽬描述

在数组中的两个数字,如果前⾯⼀个数字⼤于后⾯的数字,则这两个数字组成⼀个逆序对。输⼊⼀个数组,求出这个数组中的逆序对的总数。

输⼊⼀个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

示例 1:
输⼊: [7,5,6,4]
输出: 5
限制:0 <= 数组⻓度 <= 50000

思路及解答

暴⼒破解

⾸先,也就是数组中任意两个数,只要前⾯的数⼤于后⾯的数,就是逆序对。先来⼀次暴⼒破解:遍历任意两个数,只要符合条件,总数就增加1。

class Solution {public int reversePairs(int[] nums) {int i=0, j=0, sum=0;for( i=0; i<nums.length; i++ ){for( j=i+1; j<nums.length; j++ ){if( nums[j] < nums[i] ) sum++;}}return sum;}
}
  • 时间复杂度​:O(n²) - 对于每个元素,都需要与后续所有元素比较
  • 空间复杂度​:O(1) - 只使用常数级别额外空间

归并排序法(推荐)

在归并排序的基础上稍微改动即可。以数组[8,6,4,2,7,5,3,1]为例:

我们可以发现,其实在合并的过程中,两个有序的数组,可以直接计算出逆序数组的个数。我们以[8,6,4,2,7,5,3,1] ,实际上分为 [8,6,4,2] 和 [7,5,3,1] ,逆序的个数为第⼀部分 [8,6,4,2] 中的逆序个数+第⼆部分 [7,5,3,1] 中的逆序个数,还有第三部分是 [8,6,4,2] 中的元素相对 [7,5,3,1] 的逆序个数。

分为两半之后的逆序个数,⼀看就是分治法,递归即可,⽽两部分的相对逆序,我们可以在合并有序数组的时候得出。

合并的时候使⽤双指针, i 指向第⼀个数组的第⼀个元素,j指向第⼆个数组的第⼀个元素。哪⼀个元素⼩,就将该元素写⼊新的数组中,同时指针后移。

如果第⼆个数组中的元素⼩于第⼀个数组中的元素,那么就构成了逆序对,逆序对的个数:如果中间分隔是索引是 mid ,那么构成逆序对的个数为 mid-i+1 。

核心原理:​​当左子数组的当前元素 temp[i]大于右子数组的当前元素 temp[j]时,左子数组中从 imid的所有元素都与 temp[j]构成逆序对,因为左右子数组都是有序的

public class Solution35 {public static void main(String[] args) {int[] nums = {8, 6, 4, 2, 7, 5, 3, 1};Solution35 solution35 = new Solution35();int result = solution35.InversePairs(nums);System.out.println(result);}public int InversePairs(int[] array) {if (array == null || array.length < 2) {return 0;}int[] nums = new int[array.length];return getNums(array, nums, 0, array.length - 1) % 1000000007;}public int getNums(int[] array, int[] nums, int left, int right) {if (left >= right) {return 0;}int mid = left + (right - left) / 2;int leftNum = getNums(array, nums, left, mid) % 1000000007;int rightNum = getNums(array, nums, mid + 1, right) % 1000000007;return leftNum + rightNum + mergeNum(array, nums, left, mid, right);}public int mergeNum(int[] array, int[] nums, int left, int mid, int right) {for (int i = left; i <= right; i++) {nums[i] = array[i];}int count = 0;int i = left, j = mid + 1;for (int k = left; k <= right; k++) {if (i == mid + 1) {array[k] = nums[j];j++;} else if (j == right + 1) {array[k] = nums[i];i++;} else if (nums[i] <= nums[j]) {array[k] = nums[i];i++;} else {array[k] = nums[j];j++;count = (count + (mid - i + 1)) % 1000000007;}}return count % 1000000007;}
}
  • 时间复杂度​:O(n log n) - 与归并排序相同
  • 空间复杂度​:O(n) - 需要临时数组存储

有⼀个很坑的地⽅:只要涉及到加和的地⽅都有可能溢出,⼀旦溢出就会导致结果出错,数据量⼤,很难调试。所以凡是涉及到加和的地⽅都要 % 1000000007 。

树状数组法

利用树状数组(Fenwick Tree)和离散化技术统计逆序对

import java.util.*;public class Solution {private int mod = 1000000007;public int InversePairs(int[] nums) {if (nums == null || nums.length == 0) return 0;// 离散化处理:将原数组映射到紧凑的整数范围int[] sorted = nums.clone();Arrays.sort(sorted);// 创建映射:原数组值 -> 离散化后的索引(从1开始)Map<Integer, Integer> mapping = new HashMap<>();int index = 1;for (int num : sorted) {if (!mapping.containsKey(num)) {mapping.put(num, index++);}}// 使用树状数组统计逆序对FenwickTree tree = new FenwickTree(index - 1);int count = 0;// 从右向左遍历,统计每个元素左边比它小的元素数量for (int i = nums.length - 1; i >= 0; i--) {int pos = mapping.get(nums[i]);count = (count + tree.query(pos - 1)) % mod; // 查询比当前元素小的数量tree.update(pos, 1); // 更新树状数组}return count;}// 树状数组实现class FenwickTree {private int[] tree;private int n;public FenwickTree(int size) {this.n = size;this.tree = new int[size + 1];}// 低位操作private int lowBit(int x) {return x & (-x);}// 更新操作:在位置x增加valuepublic void update(int x, int value) {while (x <= n) {tree[x] = (tree[x] + value) % mod;x += lowBit(x);}}// 查询操作:求前x项的和public int query(int x) {int sum = 0;while (x > 0) {sum = (sum + tree[x]) % mod;x -= lowBit(x);}return sum;}}
}
  • 间复杂度​:O(n log n) - 离散化O(n log n),树状数组操作O(log n)
  • 空间复杂度​:O(n) - 树状数组和映射表空间

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/938005.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年最新推荐!西宁种植牙医院推荐榜单:助您精准选靠谱口腔机构

当前口腔种植需求持续增长,种植牙凭借出色的功能性与美观性,成为缺牙患者修复的首选方式。然而,西宁地区口腔种植机构数量繁杂,资质、技术与服务质量差距显著 —— 部分机构存在医疗设备陈旧、消毒流程不规范、专家…

2025 年太阳能厂家最新推荐:全场景系统企业综合实力榜,含热水 / 发电 / 光伏热等领域优质品牌测评

随着双碳战略深入推进,太阳能行业成为能源转型核心赛道,但市场乱象却制约着用户选择。一方面,大量企业涌入导致技术水平悬殊,部分厂商缺乏核心研发能力,仅靠简单组装设备投放市场,产品性能不稳定、能耗控制失效等…

苦逼,通宵肝了两个月!测试开发导航网站终于上线了!

大家好,我是狂师。 8月底开始,通宵肝了两个月(国庆节期间,牙都被肝疼了,苦逼~),我的第二个面向C端用户的网站:测试开发导航(https://testfather.cn/)正式上线了。 what? 这是一个啥网站呢? 简单来说, 这是…

鸿蒙应用开发从入门到实战(二十三):一文搞懂ArkUI弹性布局

ArkUI提供了各种布局组件用于界面布局,本文研究使用Flex组件实现弹性布局。大家好,我是潘Sir,持续分享IT技术,帮你少走弯路。《鸿蒙应用开发从入门到项目实战》系列文章持续更新中,陆续更新AI+编程、企业级项目实…

2025 金属复合板厂家最新推荐排行榜:实力厂家产能定制服务全景解析,选购指南必备

金属复合板在建筑装饰、工业制造等领域的应用日益广泛,但行业供需失衡与乱象让采购方陷入选择困境。部分企业缺乏核心技术,产品存在防火等级不足、耐候性差等问题,难以适配医院、化工等特殊场景;产能不稳定导致订单…

CCPC2024成都 游记(VP) 未完成以及一些找补的话

说是 $VP$ 其实是板刷。省流 说是 \(VP\) 其实是板刷。10.7 内含剧透,请vp后再来。 不是题解!!!!!!! 赛前 一点开始的,故中午没睡午觉,第一次和 \(Moemi\) 和 \(jry\) 组队打,是一个尝试,不过赛前就说 \(j…

CF1439C Greedy Shopping

CF1439C Greedy Shopping给定一个长为 \(n\) 的单调不增的数组 \(a\),有 \(q\) 次操作:给出 \(x,y\),令区间 \([1,x]\) 内的数对 \(y\) 取 \(\max\)。给出 \(x,y\),从左到右遍历 \([x,n]\) 内的每个数,如果 \(a_i…

Python3 random 模块

Python3 random 模块random 是 Python 标准库中用于生成伪随机数的模块,提供了丰富的随机数生成和随机操作功能,适用于模拟、抽样、打乱顺序等场景。它生成的随机数基于特定算法(伪随机),但对大多数应用场景已足够…

完整教程:AI应用生成平台:数据库、缓存与存储

完整教程:AI应用生成平台:数据库、缓存与存储pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

CCPC2022绵阳 游记(VP)

主包犯蠢浪费 $150min$,从铜首掉下铜中,$5t$ 罚时 $692$。省流 主包犯蠢浪费 \(150min\),从铜首掉下铜中,\(5t\) 罚时 \(692\)。10.14 内含剧透,请vp后再来。 不是题解!!!!!!! 赛前 晚上叶神有课,提前到 …

2025 年电缆桥架生产厂家最新推荐排行榜:含北方 / 河北 / 瓦楞 / 防火 / 模压 / 镀锌桥架品牌及合作案例盘点

在电力传输、建筑基建等关键领域,电缆桥架作为线路支撑核心设备,其质量直接决定工程安全与运维稳定性。当前市场中,部分厂家存在工艺粗糙、防腐性能不足、承重不达标等问题,导致桥架寿命缩短、线路故障频发,增加企…

详细介绍:[创业之路-640]:通信行业供应链 - 通信网的发展趋势:IP化统一 、云网融合 、算网协同 、FMC(固定移动融合)、空天地一体化

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025 年胰岛素泵厂家最新推荐排行榜:国产实力厂家技术、口碑及全场景适配方案全景解析软针植入/平衡式留置针/无异物感胰岛素泵厂家推荐

随着糖尿病患者对精准控糖需求的不断提升,胰岛素泵作为核心治疗设备,其技术迭代速度与产品适配性备受关注。当前市场中,既有深耕多年的成熟品牌持续创新,也有新兴企业凭借差异化技术崭露头角,但产品质量、输注精度…

2025 年国内磨床厂家最新推荐榜:聚焦平面磨床外圆磨床等品类,助力企业精准选优质设备

当前磨床市场品类繁杂,平面磨床、外圆磨床、数控磨床等产品质量差异显著,众多企业在选购时常陷入困境。部分厂家缺乏规范质量管控,设备精度与稳定性不足,难以适配汽车、军工、工程机械等行业高标准加工需求;还有厂…

2025 年加工中心厂家最新推荐榜:覆盖立式、卧式、龙门及 850 等多规格设备,帮采购方高效选实力厂商

当前加工中心市场厂商数量繁杂,产品质量、技术实力及服务水平差异显著,汽车摩托车、军工、工程机械等行业采购方在挑选设备时,常因信息不对称难以精准定位符合需求的品牌。部分厂商技术研发薄弱、产品同质化严重,无…

进程的内存管理

> 「C语言进程虚拟内存」:栈、堆、数据段、代码段各自职责、生命周期、典型API 。一、虚拟内存总览:四个大区 任何一个程序,正常运行都需要内存资源,用来存放诸如变量、常量、函数代码等等。这些不同的内容,所…

深入理解Java内存模型与volatile关键字:从理论到实践

1. 引言:为什么需要理解内存模型? 在多核处理器成为主流的今天,并发编程已成为每个Java程序员的必备技能。然而,编写正确的并发程序远比单线程程序复杂,主要原因在于我们需要处理两个核心问题:线程之间如何通信?…

完整教程:【stm32】cube固件解析和放入工程(HAL_F4)

完整教程:【stm32】cube固件解析和放入工程(HAL_F4)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&q…

312、金缕衣

312、金缕衣312、金缕衣 唐●杜秋娘 劝君莫惜金缕衣,劝君惜取少年时。 花开堪折直须折,莫待无花空折枝。【现代诗意译】 我劝你啊 不要看重华丽衣裳 但是 一定要珍惜 青春年少美好时光花开宜折的时候 就要立即把它摘…

使用 Visual Studio 快速创建 NuGet 程序包并发布到 NuGet 官网

前言 在前面的 .NET EF Core 快速入门实战教程章节中我们创建了一个名为 EFCoreGenericRepository 的 .NET 9 通用仓储类库,今天我们来把这个 EF Core 通用仓储类库打包成 NuGet 程序包并发布到 NuGet 官网(https://…