• <leetcode c++>面试题51. 数组中的逆序对


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

    很容易想到从后往前折半插入排序时顺便记录比当前数小得数,但是这种方法在用例30的时候就超时了。。

    class Solution {
    public:
        int count(vector<int>& nums, int pivot, int st, int ed){
            int l=st,r=ed;
            if(nums[pivot]<=nums[st])return 0;
            if(nums[pivot]>nums[ed]){
                int tmp=nums[pivot];
                for(int i=st;i<=ed;i++){
                    nums[i-1]=nums[i];
                }
                nums[ed]=tmp;
                return ed-st+1;
            }
            while(l<r){
                int mid=l+(r-l)/2;
                if(nums[mid]>=nums[pivot])
                    r=mid;
                else
                    l=mid+1;
            }
            int tmp=nums[pivot];
            for(int i=st;i<l;i++){
                nums[i-1]=nums[i];
            }
            nums[l-1]=tmp;
            return l-st;
        }
        int reversePairs(vector<int>& nums) {
            //从后往前折半插入排序
            int n=nums.size();
            int res=0;
            for(int i=n-2;i>=0;i--){
                res+=count(nums,i,i+1,n-1);
            }
            return res;
        }
    };

    然后我就思考毕竟插入排序要移动数组元素,最后的总体时间复杂度是O(n^2),那么找到一个插入和比较都是logn复杂度的算法不就可以了吗,那不就是归并排序吗!

    当然,需要O(n)的额外空间,时间复杂度为O(logn)

    class Solution {
    public:
        int res=0;
    
        void merge(vector<int>& nums, int left, int mid, int right){
            vector<int> tmp(right-left+1,0);
            int l1=left,l2=mid+1,l3=0;
            while(l1<=mid&&l2<=right){
                if(nums[l1]<=nums[l2]){
                    tmp[l3++]=nums[l1++];
                    res+=(l2-mid-1);
                }
                else
                    tmp[l3++]=nums[l2++];
            }
            while(l1<=mid){
                tmp[l3++]=nums[l1++];
                res+=(l2-mid-1);
            }
            while(l2<=right)tmp[l3++]=nums[l2++];
            for(int i=left;i<=right;i++){
                nums[i]=tmp[i-left];
            }
        }
    
        void mergeSort(vector<int>& nums, int left, int right){
            if(left<right){
                int mid = left+(right-left)/2;
                mergeSort(nums,left,mid);
                mergeSort(nums,mid+1,right);
                merge(nums,left,mid,right);
            }
        }
            
        int reversePairs(vector<int>& nums) {
            //归并排序
            int n=nums.size();
            mergeSort(nums,0,n-1);
            return res;
        }
    };
  • 相关阅读:
    Oracle基础操作
    Linux的常用命令
    Javascript 上课笔记
    Linux操作指令
    css样式分类
    DW
    标准sql执行顺序
    Mysql数据库
    模拟课----需求文本
    php 发送邮件
  • 原文地址:https://www.cnblogs.com/Dancing-Fairy/p/12770553.html
Copyright © 2020-2023  润新知