zoukankan      html  css  js  c++  java
  • 剑指 Offer 51. 数组中的逆序对

    题目描述

    在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

    示例1:

    输入: [7,5,6,4]
    输出: 5
    

    限制:

    0 <= 数组长度 <= 50000
    

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof

    思路解析

    假设给定数组为[8, 10, 15, 20, 70, 9, 25, 50, 60, 100],这个数组的前一半和后一半都是有序的,那么此时这个数组的逆序对的个数应该如何统计?
    指针i指向[8, 10, 15, 20, 70]首元素,指针j指向[9, 25, 50, 60, 100]首元素,比较var(i)var(j)的大小。(这里var(i)var(j)ij指向元素的值)

    • var(i) < = var(j),则此时ij指向元素不构成逆序对,否则构成逆序对(j++);
    • var(i) < = var(j),则代表后半段的数组中,有j个元素小于var(i);(这里假设ij均从0开始)
    • 由此可统计出前半段的数组中每个元素所构成的逆序对的个数,且后半段数组中不存在逆序对。

    使用归并排序的思想,当元素分组至每组仅有一个元素时,代表该组已经有序,返回此有序数组中逆序对的个数为0,随后进行归并,并记录每次归并所产生的数组的逆序对的个数。
    时间复杂度(O(n log n)),空间复杂度(O(n))

    代码实现

    class Solution {
    private:
        vector<int> orderedArray;   // From large to small
    public:
        int reversePairs(vector<int>& nums) {
            int n = nums.size();
            vector<int> tmp(n);
            return mergeSort(nums, tmp, 0, n - 1);
        }
        int mergeSort(vector<int>& nums, vector<int>& tmp, int left, int right) {
            if(left >= right) 
                return 0;
            int mid = (left + right) / 2;
            int prev_count = mergeSort(nums, tmp, left, mid) + mergeSort(nums, tmp, mid + 1, right);
            // Merge
            int i = left;
            int j = mid + 1;
            int curr_count = 0;
            int tmp_index = left;
            while(i <= mid && j <= right) {
                if(nums[i] <= nums[j]) {
                    tmp[tmp_index] = nums[i++];
                    curr_count += (j - mid - 1);
                }
                else{
                    tmp[tmp_index] = nums[j++];
                }
                tmp_index++;
            }
            while(i <= mid){
                tmp[tmp_index++] = nums[i++];
                curr_count += (j - mid - 1);
            }
            while(j <= right)
                tmp[tmp_index++] = nums[j++];
            for(tmp_index = left; tmp_index <= right; tmp_index++)
                nums[tmp_index] = tmp[tmp_index];
            return prev_count + curr_count;
        }
    };
    
  • 相关阅读:
    DoNet:浅淡对delegate的理解
    纹理学习总结
    Vue引发的getter和setter
    JS——判断一个对象是否为空
    使用vue-axios请求geoJson数据报错的问题
    在vue-cli项目中使用echarts
    Vue中的$set的使用
    史上最全的开发和设计资源大全(转--------来源:伯乐在线)
    IOS safari浏览器登陆时Cookie无法保存的问题
    JS中const、var 和let的区别
  • 原文地址:https://www.cnblogs.com/xqmeng/p/13693588.html
Copyright © 2011-2022 走看看