剑指Offer 55. 数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
思路:运用归并排序的特点,merge的过程中如果后面区间的数字比前面区间的数字要小的话,则可以利用下标关系一次计算出当前区间中的所有逆序对,从而优化时间复杂度,缺点就是归并排序会用到一个辅助数组,所以会增加空间复杂度,也算是一种用时间换取空间的思想。因为计算逆序对直接相减就可以算出来了,所以整体的时间复杂度仍然是排序过程的时间复杂度O(nlogn),空间复杂度为O(n)
代码:
class Solution { public: int count = 0; vector<int> dummy; void merge(vector<int>& nums, int s1, int e1, int s2, int e2) { int index = s1; int pos1 = s1; int pos2 = s2; while (pos1 <= e1 && pos2 <= e2) { if (nums[pos1] <= nums[pos2]) { dummy[index++] = nums[pos1++]; } else { dummy[index++] = nums[pos2++]; count += e1 - pos1 + 1; } } while (pos1 <= e1) { dummy[index++] = nums[pos1++]; } while (pos2 <= e2) { dummy[index++] = nums[pos2++]; } for (int i = s1; i <= e2; ++i) { nums[i] = dummy[i]; } } void func(vector<int>& nums, int s, int e) { if (s >= e) return; int mid = (s + e) / 2; func(nums, s, mid); func(nums, mid+1, e); merge(nums, s, mid, mid+1, e); } int reversePairs(vector<int>& nums) { int len = nums.size(); dummy.resize(len); func(nums, 0, len - 1); return count; } };
永远渴望,大智若愚(stay hungry, stay foolish)