LeetCode第 493 题:翻转对(C++)

493. 翻转对 - 力扣(LeetCode)

暴力法

O(n^2), 简单且超时…

class Solution {
public:
    int cnt = 0;
    int reversePairs(vector<int>& nums) {
        int n = nums.size();
        for(int i = 0; i < n-1; ++i){
            for(int j = i+1; j < n; ++j){
                if(long(nums[i]) > 2*long(nums[j])) ++cnt;
            }
        }
        return cnt;
    }
};

归并

和下面两个很像:

LeetCode第 327 题:区间和的个数(C++)_qq_32523711的博客-CSDN博客

剑指 Offer 51. 数组中的逆序对_qq_32523711的博客-CSDN博客

class Solution {
public:
    int cnt = 0;
    vector<int> tmp;//只申请一次tmp数组
    void merge(vector<int> &nums, int beg, int mid, int end){
        int i = beg, j = mid+1;
        int k = 0;
        while(i <= mid && j <= end){
            if(nums[i] <= nums[j])  tmp[k++] = nums[i++];
            else   tmp[k++] = nums[j++];
        }
        while(i <= mid) tmp[k++] = nums[i++];
        while(j <= end) tmp[k++] = nums[j++];
        copy(tmp.begin(), tmp.begin() + k, nums.begin() + beg);
    }
    void merge_sort(vector<int> &nums, int beg, int end){
        if(beg >= end) return;
        int mid = beg + (end - beg)/2;
        merge_sort(nums, beg, mid);
        merge_sort(nums, mid+1, end);
        //计算符合要求的翻转对数目
        int i = beg, j = mid+1;
        while(j <= end){ //对于右半部分的每个元素
            while(i <= mid && long(nums[i]) <= 2*long(nums[j]))  ++i;
            cnt += mid - i + 1;
            ++j;
        }
        if(nums[mid] <= nums[mid+1])    return; //加一个判断,此时数组已经是有序的,不用进行后续操作了
        merge(nums, beg, mid, end);
    }
    int reversePairs(vector<int>& nums) {
        int n = nums.size();
        tmp = vector<int>(n);
        merge_sort(nums, 0, n-1);
        return cnt;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_32523711/article/details/107920845