归并排序

class Solution {
public:
    vector<int> buffer; // 辅助数组, 临时保存递归过程有序的部分
    vector<int> sortArray(vector<int>& nums) {
        int size = nums.size();
        buffer.resize(size);
        sort(nums, 0, nums.size() - 1);
        return nums;
    }
    
    void merge(vector<int> &nums, int left, int mid, int right) {
        int p1 = left;
        int p2 = mid + 1;
        int p3 = left;
        while (p1 < mid + 1 && p2 < right + 1)  {
            if (nums[p1] <= nums[p2]) {
                buffer[p3++] = nums[p1++];
            } else {
                buffer[p3++] = nums[p2++];
            }
        }
        while (p1 < mid + 1) {
            buffer[p3++] = nums[p1++];
        }
        while (p2 < right + 1) {
            buffer[p3++] = nums[p2++];
        }
        for (int i = left; i < right + 1; ++i) {
            nums[i] = buffer[i];
        }
    }
    
    void sort(vector<int> &nums, int left, int right) {
        if (left >= right) {
            return;
        }
        int mid = (left + right) >> 1;
        sort(nums, left, mid);
        sort(nums, mid + 1, right);
        merge(nums, left, mid, right);
    }
    
};

493. 翻转对

给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对

你需要返回给定数组中的重要翻转对的数量。

示例 1:

输入: [1,3,2,3,1]
输出: 2

示例 2:

输入: [2,4,3,5,1]
输出: 3

注意:

  1. 给定数组的长度不会超过50000
  2. 输入数组中的所有数字都在32位整数的表示范围内。

class Solution {
public:
    vector<int> buffer;
    int reversePairs(vector<int>& nums) {
        buffer.resize(nums.size());
        return help(nums, 0, nums.size() - 1);
    }
    
    int help(vector<int>& nums, int left, int right) {
        if (left >= right) {
            return 0;
        }
        int mid = (left + right) >> 1;
        int l = help(nums, left, mid);
        int r = help(nums, mid + 1, right);
        return l + r + merge(nums, left, mid, right);
    }
    
    int merge(vector<int> &nums, int left, int mid, int right) {
        int p1 = left;
        int p2 = mid + 1;
        int p3 = left;
        
        // 统计数量(修复 *2 溢出)
        int i = left, j = mid + 1;
        int ans = 0;
        while (i < mid + 1) {
            while (j < right + 1 && (long long)nums[i] > 2LL * nums[j]) {
                ++j;
            }
            ans += j - (mid + 1);
            ++i;
        }
        
        // 合并排序
        while (p1 < mid + 1 && p2 < right + 1)  {
            if (nums[p1] <= nums[p2]) {
                buffer[p3++] = nums[p1++];
            } else {
                buffer[p3++] = nums[p2++];
            }
        }
        while (p1 < mid + 1) {
            buffer[p3++] = nums[p1++];
        }
        while (p2 < right + 1) {
            buffer[p3++] = nums[p2++];
        }
        for (int i = left; i <= right; ++i) {
            nums[i] = buffer[i];
        }
        return ans;
    }
};