当前位置:网站首页>力扣 剑指 Offer 51. 数组中的逆序对
力扣 剑指 Offer 51. 数组中的逆序对
2022-07-28 12:20:00 【三更鬼】
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目来源:https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
大致题意:
给定一个数组,求出数组中逆序对的个数,逆序对的定义为:
- 设有 i < j,若 nums[i] > nums[j] 则 nums[i] 与 nums[j] 构成逆序对
思路
若有两个升序数组 nums1 和 nums2,那么如何比较这两个升序数组合并后的逆序对个数?
- 首先,由于两个数组本身是升序数组,所以数组本身中不存在逆序对
- 那么,这两个升序数组合并后的逆序对个数取决与前一个数组中有多少元素大于后一个数组
使用双指针 i 和 j 分别表示两个升序数组的遍历位置
若 nums1[i] 大于 nums2[j],那么 i 至前一个数组末尾所有元素都大于 nums2[j],这些元素都与 nums2[j] 构成逆序对,统计个数并后移指针 j;
若 nums1[i] 不大于 nums2[j],那么指针 i 后移
通过上述方法可以统计两个升序数组的逆序对个数,那么若两个数组不是升序数组呢?
即若有两个数组 nums1 和 nums2,那么如何比较这两个数组合并后的逆序对个数?
- 首先,统计 nums1 和 nums2 本身的逆序对个数,然后将两个数组排序
- 按照上述方法计算两个升序数组合并后的逆序对个数
于是就可以使用归并排序的思路,在归并排序的同时计算逆序对个数
具体看代码:
public int reversePairs(int[] nums) {
int n = nums.length;
return merge(nums, new int[n], 0, n - 1);
}
/** * 归并排序,返回 [left, right] 区间内逆序对个数 * @param nums * @param temp * @param left * @param right * @return */
public int merge(int[] nums, int[] temp, int left, int right) {
if (left >= right) {
return 0;
}
int mid = (left + right) >> 1;
// 归并排序左半
int leftCount = merge(nums, temp, left, mid);
// 归并排序右半
int rightCount = merge(nums, temp, mid + 1, right);
// 左半最大元素不大于右半最小元素,证明两个区间合并后不会出现新的逆序对
if (nums[mid] <= nums[mid + 1]) {
return leftCount + rightCount;
}
// 合并左右区间并计算合并产生的逆序对
int crossCOunt = mergeAndCount(nums, temp, left, right);
return leftCount + rightCount + crossCOunt;
}
/** * 合并两个区间并计算合并产生的逆序对 * * @param nums * @param temp * @param left * @param right * @return */
public int mergeAndCount(int[] nums, int[] temp, int left, int right) {
// 先将合并区间元素拷贝到临时数组
for (int i = left; i <= right; i++) {
temp[i] = nums[i];
}
// 左右区间边界
int mid = (left + right) >> 1;
// 做右指针
int leftIdx = left;
int rightIdx = mid + 1;
// 逆序对个数
int count = 0;
// 合并区间
for (int i = left; i <= right; i++) {
if (leftIdx == mid + 1) {
nums[i] = temp[rightIdx++];
} else if (rightIdx == right + 1) {
nums[i] = temp[leftIdx++];
} else if (temp[leftIdx] <= temp[rightIdx]) {
nums[i] = temp[leftIdx++];
} else {
// 左指针当前元素大于右指针当前元素,统计逆序对个数
count += mid - leftIdx + 1;
nums[i] = temp[rightIdx++];
}
}
return count;
}
边栏推荐
- Protective bearish strategy
- Dry goods -- encapsulated anti shake and throttling method in the project
- Android engineers, how to use kotlin to provide productivity?
- 夜神模拟器抓包微信小程序
- Tidb 6.x in action was released, a summary of 6.x practices that condense the collective wisdom of the community!
- gicv3 spi register
- nport串口服务器配置网址(串口服务器是不是网口转串口)
- Black cat takes you to learn UFS agreement part 2: Interpretation of UFS related terms
- C语言学生成绩管理系统详解[通俗易懂]
- 《如何打一场数据挖掘赛事》入门版
猜你喜欢

Unity—“合成大西瓜”小游戏笔记

FFT海浪模拟

Bear market spread portfolio

今日睡眠质量记录75分

How much do you know about JVM memory management

Form for real-time custom verification

Risk analysis of option trading

Bull spread portfolio
![[embedded C foundation] Part 6: super detailed explanation of common input and output functions](/img/eb/69264bc0d8e9349991b7b9e1b8ca22.png)
[embedded C foundation] Part 6: super detailed explanation of common input and output functions

半波整流点亮LED
随机推荐
我抄底了被清算的NFT,却被OpenSea上了锁
Shell basic concepts and variables
蓝桥集训(附加面试题)第七天
GO语言-栈的应用-表达式求值
leetcode-136.只出现一次的数字
Leetcode notes 566. Reshaping the matrix
沾上趣店,都得道歉?
What is the optimization method of transaction and database
Chapter 6 提升
The difference between sessionstorage, localstorage and cookies
With 433 remote control UV lamp touch chip-dlt8sa20a-jericho
Leetcode notes 118. Yang Hui triangle
[embedded C foundation] Part 8: explanation of C language array
Leetcode 笔记 566. 重塑矩阵
How to design a second kill system?
Aragon创建DAO polygon BSC测试网
Guide for using IP phone system and VoIP system
[FPGA]: ISE generates MCS file and burning process
《如何打一场数据挖掘赛事》入门版
Intra prediction and transform kernel selection based on Neural Network