题解 | #数组中的逆序对#
数组中的逆序对
https://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @return int整型
*/
int res = 0;
//合并过程
void merge(vector<int>& nums,int l,int r,int mid){
int left = l;
int right = mid + 1;
//申请一个临时数组
int index = 0;
vector<int> tmp(r - l + 1);
//存入临时数组,此时临时数组是有序的
while(left <= mid && right <= r){
//如果左边小于右边,则正常插入
if(nums[left] <= nums[right]){
tmp[index] = nums[left];
left += 1;
}
else{//如果右边小于左边那么说明存在逆序对,
tmp[index] = nums[right];
//如何判断有多少个逆序对呢?因为当前遍历的左边区间下标为index的元素大于右边的,所以,左边index以后的元素都要大于当前下标为right的元素,所以用mid - left + 1.
res = (res + mid - left + 1) % 1000000007;
right += 1;
}
index += 1;
}
while(left <= mid){
tmp[index] = nums[left];
left += 1;
index += 1;
}
while(right <= r){
tmp[index] = nums[right];
right += 1;
index += 1;
}
for(int i = 0;i < tmp.size();i++){
nums[l] = tmp[i];
l += 1;
}
vector<int>(tmp).swap(tmp);
}
//归并排序
void sort(vector<int>& nums,int l,int r){
if(l >= r)return;
int mid = l + (r - l) / 2;
//切割左边的部分
sort(nums,l,mid);
//切割右边的部分
sort(nums,mid + 1,r);
//当左右边都有序的时候,就合并
merge(nums,l,r,mid);
}
int InversePairs(vector<int>& nums) {
// write code here
sort(nums,0,nums.size() - 1);
for(int val : nums){
cout << val << " ";
}
return res;
}
};
该题使用归并排序,通过归并排序的递归分割原数组,直到当前子数组长度为1,此时每个段都是有序的,然后将左右有序数组合并起来,在合并的过程中,如果左边遍历到的元素大于右边遍历到的元素,也就是存在逆序对,此时左边遍历到的位置的后面的所有元素都会大于右边的元素,这可以确定逆序对的数量,也就是mid - left + 1。该题解的时间复杂度是O(nlogn),空间复杂度是 O(n)。
叮咚买菜工作强度 89人发布

查看14道真题和解析