
💡 算法核心思路
逆序对(前一天股价高于后一天)的产生分为三种情况:
- 两个元素都在左半部分(递归求解)。
- 两个元素都在右半部分(递归求解)。
- 一个在左半部分,一个在右半部分(合并时统计)。
归并排序的"合并两个阶段"恰好是左右子数组都有序的状态,此时可以高效地统计跨区间的逆序对。
💻 代码逐段解析
1. 初始化与入口
int[] tmp; // 全局辅助数组,避免递归中频繁创建数组开辟内存
public int reversePairs(int[] nums) {
int n=nums.length;
tmp=new int[n];
return mergeSort(nums,0,n-1);
}
2. 递归分治(拆分)
public int mergeSort(int[] nums,int left,int right){
if(left>right)return 0; // 递归终止条件(子数组长度为1或0)
int ret=0;
int mid=(left+right)/2; // 取中间点划分
ret+=mergeSort(nums,left,mid); // 统计左子数组内部的逆序对
ret+=mergeSort(nums,mid+1,right); // 统计右子数组内部的逆序对
3. 合并与统计逆序对(核心重点)
int cur1=left,cur2=mid+1,i=0;
while(cur1<=mid&&cur2<=right){
if(nums[cur1]<=nums[cur2]){
tmp[i++]=nums[cur1++]; // 左元素小,不构成逆序对,直接放入临时数组
}else{
ret+=mid-cur1+1; // ⭐核心公式:左子数组中 cur1 及右侧所有元素都大于当前右元素,直接统计数量
tmp[i++]=nums[cur2++]; // 将右元素放入临时数组
}
}