可以和面试官对一下是否需要修改原数组
题解:
https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/java-gui-bing-fa-by-1yx/
将较大规模的问题拆解为若干个子问题,将子问题解决后,原文题也得到了解决
复杂度分析:
时间复杂度:O(NlogN),这里 N 是数组的长度。复杂度是归并排序的时间复杂度,直接看递归树的结点个数或者使用主定理分析,归并的回收每一步计算逆序对的个数是 O(1) 的;
空间复杂度:O(N)。
class Solution {
public:
int reversePairs(vector<int>& nums) {
if(nums.size() == 0) {
return 0;
}
return reverse_pair(nums, 0, nums.size()-1);
}
int reverse_pair(vector<int>& nums, int left, int right) {
if(left >= right) {
return 0;
}
int mid = left + (right - left)/2;
int left_count = reverse_pair(nums, left, mid);
int right_count = reverse_pair(nums, mid+1, right);
return left_count + right_count + merge_and_count(nums, left, mid, mid+1, right);
}
int merge_and_count(vector<int>& nums, int begin1, int end1, int begin2, int end2) {
//int* temp = new int[end2-begin1+1];
vector<int> temp(end2-begin1+1, 0);
int count = 0;
int i = begin1;
int j = begin2;
int k = 0;
while(i <= end1 && j <= end2) {
// 如果nums[i]比nums[j]大,则[i,mid]间的数,都是nums[j]的逆序对
count += nums[i] > nums[j]? end1 - i + 1:0;
temp[k++] = nums[i] <= nums[j]? nums[i++]:nums[j++];
}
while(i <= end1) {
temp[k++] = nums[i++];
}
while(j <= end2) {
temp[k++] = nums[j++];
}
// 将排好序的temp,放入nums中
for(int i = 0; i < k; ++i) {
nums[begin1+i] = temp[i];
}
return count;
}
};
归并排序
#include<stdio.h>
#include<stdlib.h>
// 将两组有序的 合并成一个新的
void Sort(int* arr,int low,int high)
{
// 分组
int iBegin1 = low;
int iEnd1 = (low+high)/2;
int iBegin2 = iEnd1+1;
int iEnd2 = high;
// 申请一个新的数组 装 排好序的结果
int* temp = (int*)malloc(4*(high-low+1));
int k = 0;
// 比较每一组的 第一个元素
while(iBegin1 <= iEnd1 && iBegin2 <= iEnd2)
{
// 找一个小的 存到 temp
if(arr[iBegin1] < arr[iBegin2])
temp[k++] = arr[iBegin1++];
else
temp[k++] = arr[iBegin2++];
}
// 有一组有剩余
while(iBegin1 <= iEnd1)
temp[k++] = arr[iBegin1++];
while(iBegin2 <= iEnd2)
temp[k++] = arr[iBegin2++];
// 把 新的数组的元素 放回到对应的位置
for(k=0;k<(high-low+1);k++)
arr[low+k] = temp[k];
free(temp);
}
void MergeSort(int* arr,int low,int high)
{
if(low < high) // 有两个以上要排序
{
int mid = (low+high)/2;
// 分组
MergeSort(arr,low,mid);
MergeSort(arr,mid+1,high);
// 合并
Sort(arr,low,high);
}
}
void AA(int* arr,int n)
{
if(arr == NULL || n <= 0)
return;
MergeSort(arr,0,n-1);
}
int main()
{
int arr[10] = {2,3,1,4,5,2,6,8,7,0};
AA(arr,10);
for(int i=0;i<10;i++)
printf("%d ",arr[i]);
system("pause");
return 0;
}
class Solution {
public:
int mergeSort(vector<int>& nums, vector<int>& tmp, int l, int r) {
if (l >= r) {
return 0;
}
int mid = (l + r) / 2;
int inv_count = mergeSort(nums, tmp, l, mid) + mergeSort(nums, tmp, mid + 1, r);
int i = l, j = mid + 1, pos = l;
while (i <= mid && j <= r) {
if (nums[i] > nums[j]) {
tmp[pos] = nums[j];
++j;
inv_count += (mid - i + 1);
} else {
tmp[pos] = nums[i];
++i;
}
++pos;
}
for (int k = i; k <= mid; ++k) {
tmp[pos++] = nums[k];
}
for (int k = j; k <= r; ++k) {
tmp[pos++] = nums[k];
}
copy(tmp.begin() + l, tmp.begin() + r + 1, nums.begin() + l);
return inv_count;
}
int reversePairs(vector<int>& nums) {
int n = nums.size();
vector<int> tmp(n);
return mergeSort(nums, tmp, 0, n - 1);
}
};