一、题目描述
二、解题思路
典型的归并排序方法
怎么计算count
呢?
在每次归并进行比较时
- 如果
nums[i] <= nums[j]
:说明当前位置没有逆序,继续向下比较; - 如果
nums[i] > nums[j]
,说明在前半段中,位置i
的已经都比nums[j]
大了- 前半段中位置
i
及其后面的数字一定比nums[j]
大。 - 确定前半段比
nums[j]
大的个数:注意是“在前半段中i
及其后面的数字一定比nums[j]
大”,那么本轮结果就是i
到前半段结尾的这段区间的个数,为mid - i + 1
。
- 前半段中位置
之后递归就好了
三、解题代码
LeetCode
代码
class Solution {
public:
int reversePairs(vector<int>& nums) {
auto len = nums.size();
if(len <= 1) return 0;
else return MergeSort(nums, 0, len - 1);
}
private:
int MergeSort(vector<int>& nums, int left, int right){
if(left >= right) return 0;
int mid = left + (right - left) / 2;
int count = MergeSort(nums, left, mid) + MergeSort(nums, mid + 1, right) + Merge(nums, left, mid, right);
return count;
}
int Merge(vector<int>& nums, int left, int mid, int right){
auto tmp = new int[right - left + 1];
int i = left, j = mid + 1, tmp_cur = 0;
int count = 0;
while(i <= mid && j <= right){
if(nums[i] <= nums[j])
tmp[tmp_cur++] = nums[i++];
else{
tmp[tmp_cur++] = nums[j++];
count += mid - i + 1;
}
}
while(i <= mid) tmp[tmp_cur++] = nums[i++];
while(j <= right) tmp[tmp_cur++] = nums[j++];
auto tmp_len = right - left + 1;
for(int i = 0; i < tmp_len; i++)
nums[left + i] = tmp[i];
delete []tmp;
tmp = nullptr;
return count;
}
};
剑指Offer
代码
/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.
Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/
//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================
// 面试题51:数组中的逆序对
// 题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组
// 成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
#include <cstdio>
int InversePairsCore(int *data, int *copy, int start, int end);
int InversePairs(int *data, int length);
/*
int InversePairs(int *data, int length)
{
if (data == nullptr || length < 0)
return 0;
int *copy = new int[length];
for (int i = 0; i < length; ++i)
copy[i] = data[i];
int count = InversePairsCore(data, copy, 0, length - 1);
delete[] copy;
return count;
}
int InversePairsCore(int *data, int *copy, int start, int end)
{
if (start == end)
{
copy[start] = data[start];
return 0;
}
int length = (end - start) / 2;
int left = InversePairsCore(copy, data, start, start + length);
int right = InversePairsCore(copy, data, start + length + 1, end);
// i初始化为前半段最后一个数字的下标
int i = start + length;
// j初始化为后半段最后一个数字的下标
int j = end;
int indexCopy = end;
int count = 0;
while (i >= start && j >= start + length + 1)
{
if (data[i] > data[j])
{
copy[indexCopy--] = data[i--];
count += j - start - length;
}
else
{
copy[indexCopy--] = data[j--];
}
}
for (; i >= start; --i)
copy[indexCopy--] = data[i];
for (; j >= start + length + 1; --j)
copy[indexCopy--] = data[j];
return left + right + count;
}
*/
int Merge(int *data, int *copy, int start, int mid, int end)
{
int i = start, j = mid + 1, tmp_cur = start;
int count = 0;
while (i <= mid && j <= end)
{
if (data[i] <= data[j])
copy[tmp_cur++] = data[i++];
else
{
copy[tmp_cur++] = data[j++];
count += mid - i + 1;
}
}
while (i <= mid)
copy[tmp_cur++] = data[i++];
while (j <= end)
copy[tmp_cur++] = data[j++];
for (int i = start; i <= end; i++)
data[i] = copy[i];
return count;
}
int InversePairsCore(int *data, int *copy, int start, int end)
{
if (start >= end)
return 0;
int mid = (start + end) >> 1;
int count = InversePairsCore(data, copy, start, mid) + InversePairsCore(data, copy, mid + 1, end) + Merge(data, copy, start, mid, end);
return count;
}
int InversePairs(int *data, int length)
{
if (data == nullptr || length <= 1)
return 0;
auto copy = new int[length];
auto count = InversePairsCore(data, copy, 0, length - 1);
delete[] copy;
return count;
}
// ====================测试代码====================
void Test(char *testName, int *data, int length, int expected)
{
if (testName != nullptr)
printf("%s begins: ", testName);
if (InversePairs(data, length) == expected)
printf("Passed.\n");
else
printf("Failed.\n");
}
void Test1()
{
int data[] = {1, 2, 3, 4, 7, 6, 5};
int expected = 3;
Test("Test1", data, sizeof(data) / sizeof(int), expected);
}
// 递减排序数组
void Test2()
{
int data[] = {6, 5, 4, 3, 2, 1};
int expected = 15;
Test("Test2", data, sizeof(data) / sizeof(int), expected);
}
// 递增排序数组
void Test3()
{
int data[] = {1, 2, 3, 4, 5, 6};
int expected = 0;
Test("Test3", data, sizeof(data) / sizeof(int), expected);
}
// 数组中只有一个数字
void Test4()
{
int data[] = {1};
int expected = 0;
Test("Test4", data, sizeof(data) / sizeof(int), expected);
}
// 数组中只有两个数字,递增排序
void Test5()
{
int data[] = {1, 2};
int expected = 0;
Test("Test5", data, sizeof(data) / sizeof(int), expected);
}
// 数组中只有两个数字,递减排序
void Test6()
{
int data[] = {2, 1};
int expected = 1;
Test("Test6", data, sizeof(data) / sizeof(int), expected);
}
// 数组中有相等的数字
void Test7()
{
int data[] = {1, 2, 1, 2, 1};
int expected = 3;
Test("Test7", data, sizeof(data) / sizeof(int), expected);
}
void Test8()
{
int expected = 0;
Test("Test8", nullptr, 0, expected);
}
int main(int argc, char *argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
return 0;
}
四、运行结果
InversePairs.cpp:138:61: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Test("Test1", data, sizeof(data) / sizeof(int), expected);
^
InversePairs.cpp: In function 'void Test2()':
InversePairs.cpp:147:61: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Test("Test2", data, sizeof(data) / sizeof(int), expected);
^
InversePairs.cpp: In function 'void Test3()':
InversePairs.cpp:156:61: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Test("Test3", data, sizeof(data) / sizeof(int), expected);
^
InversePairs.cpp: In function 'void Test4()':
InversePairs.cpp:165:61: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Test("Test4", data, sizeof(data) / sizeof(int), expected);
^
InversePairs.cpp: In function 'void Test5()':
InversePairs.cpp:174:61: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Test("Test5", data, sizeof(data) / sizeof(int), expected);
^
InversePairs.cpp: In function 'void Test6()':
InversePairs.cpp:183:61: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Test("Test6", data, sizeof(data) / sizeof(int), expected);
^
InversePairs.cpp: In function 'void Test7()':
InversePairs.cpp:192:61: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Test("Test7", data, sizeof(data) / sizeof(int), expected);
^
InversePairs.cpp: In function 'void Test8()':
InversePairs.cpp:199:39: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Test("Test8", nullptr, 0, expected);
^
Test1 begins: Passed.
Test2 begins: Passed.
Test3 begins: Passed.
Test4 begins: Passed.
Test5 begins: Passed.
Test6 begins: Passed.
Test7 begins: Passed.
Test8 begins: Passed.