分治归并,LCR170交易逆序对的总数 力扣315.计算右侧小于当前元素的个数力扣493.翻转对

目录

LCR170交易逆序对的总数

力扣315.计算右侧小于当前元素的个数

力扣493.翻转对


LCR170交易逆序对的总数

我那个时候很疑问,左边和右边的怎么统计呢,我总不能说是光实现左右,不实现别的吧,于是我写了一下,边写边发现,左边的也可以慢慢拆分成一左一右的,因为假如有两个,那么他就分为一左一右,这样就清楚了,他计算时候,会把左边和右边统计上

class Solution {
    public int reversePairs(int[] record) {
       return mergeSort(record,0,record.length-1);
    }
    public int mergeSort(int[]record,int left,int right){
        if(left>=right){return 0; }
        int mid=(right+left)/2;
        int ret=mergeSort(record,left,mid)+mergeSort(record,mid+1,right);
        
        //合并两个有序数组[left,mid][mid+1,right]
        int []tmp=new int[right-left+1];
        int cur1=left;
        int cur2=mid+1;
        int k=0;
        while(cur1<=mid&&cur2<=right){
       if(record[cur1]<=record[cur2]){
        tmp[k++]=record[cur1++];
       }else{
        tmp[k++]=record[cur2++];
        ret+=mid-cur1+1;
       }
     }
     while(cur1<=mid)tmp[k++]=record[cur1++];
     while(cur2<=right)tmp[k++]=record[cur2++];
     k=0;
     for(int i=left;i<=right;i++){
        record[i]=tmp[k++];
     }
     return ret;
    }
}

力扣315.计算右侧小于当前元素的个数

我觉得从这里,你可以看到上面的题的影子,但是也有不同,不同的点在哪呢?

那就是他要求的是每个数对应的逆序对个数,所以你需要找到,其中的破局之道,即从上一个模版中,摘出核心,然后加一些他的东西,我刚开始是想用哈希表,但是又在想老师说的会不会有重复问题,所以不能使用哈希表,而是用下标保存索引。

class Solution {
    List<Integer>a;
    int[]index;
    int []ret;
    public List<Integer> countSmaller(int[] nums) {
    a=new ArrayList<>();
    ret=new int[nums.length];index=new int[nums.length];
    for(int i=0;i<nums.length;i++){
        index[i]=i;
    }
    mergeSort(nums,0,nums.length-1);
    for(int i=0;i<nums.length;i++){
        a.add(ret[i]);
    }
    return  a;
    }
    public void mergeSort(int []nums,int left,int right){
        if(left>=right)return;
        int mid=(left+right)/2;
        int []tmp=new int[right-left+1];
        int []index2=new int[right-left+1];
//[left,mid]  [mid+1,right]
        mergeSort(nums,left,mid);
        mergeSort(nums,mid+1,right);
        int cur1=left;
        int cur2=mid+1;
        int k=0;
        int p=0;
        while(cur1<=mid&&cur2<=right){
            if(nums[cur1]>nums[cur2]){
//这个是部分的索引,相当于未合并的两个小的。
                index2[k]=index[cur1];
//index是总体的索引,index[cur1]这个是存储的是对应位置,
                ret[index[cur1]]+=right-cur2+1;
                tmp[k++]=nums[cur1++];    
            }else{
                index2[k]=index[cur2];
                tmp[k++]=nums[cur2++];
            }
        }
        
        while(cur1<=mid){index2[k]=index[cur1]; tmp[k++]=nums[cur1++];}
        while(cur2<=right){index2[k]=index[cur2]; tmp[k++]=nums[cur2++];}
        k=0;
      for(int i=left;i<=right;i++){
//最后的合并
        index[i]=index2[k];
        nums[i]=tmp[k++];}
    }
}

力扣493.翻转对

​​​​​​​

分治,逆序对的思路,但是稍微有偏差,他的统计翻转对不能放在归并数组里面,

class Solution {
        int ret=0;
        int []index;
        public  int reversePairs(int[] nums) {
            index=new int[nums.length];
            for(int i=0;i<nums.length;i++){
                index[i]=i;
            }
            return mergeSort(nums,0,nums.length-1);
        }
        public int mergeSort(int[]nums,int left,int right){
            if(left>=right)return 0;
            int mid=(left+right)/2;
            mergeSort(nums,left,mid);
            mergeSort(nums,mid+1,right);
            int[]tmp=new int[right-left+1];
            int[]index2=new int[right-left+1];
            int cur1=left;
            int cur2=mid+1;
            int k=0;
          

            while(cur1<=mid&&cur2<=right){
//检查是不是符合翻转对不能条件
                if(index[cur1]<index[cur2]&&(long)nums[cur1]>(long)2*nums[cur2]){
                    ret+=right-cur2+1;
                    cur1++;}
//不符合则看下一个
                else{
                    cur2++;
                    }
                }
//指针重置
            cur1=left;
            cur2=mid+1;


            while(cur1<=mid&&cur2<=right){
                if(nums[cur1]>nums[cur2]){
                    index2[k]=index[cur1];
                    tmp[k++]=nums[cur1++];
                }else{
                    index2[k]=index[cur2];
                    tmp[k++]=nums[cur2++];
                }
            }

            while(cur1<=mid){index2[k]=index[cur1];tmp[k++]=nums[cur1++];}
            while(cur2<=right){index2[k]=index[cur2];tmp[k++]=nums[cur2++];}
            k=0;
            for(int i=left;i<=right;i++){
                index[i]=index2[k];
                nums[i]=tmp[k++];
            }
            return ret;
        }
}

题解与我写的有细微差别,就是在它相当于更快的进行一个while循环,但是实际的差别并不大,都是看cur2是否符合,假如符合的话就ret=right-cur2+1,假如不符合,就去cur2++看一看cur2比较小的那个能不能符合要求,假如都不符合要求,那么就直接退出循环

下面这个是保存cur1的区间去统计。因此不用写cur2,当然这里也对cur2进行了判断,假如直接可能越界的情况。

class Solution {
        int ret=0;
        int []index;
        public  int reversePairs(int[] nums) {
            index=new int[nums.length];
            for(int i=0;i<nums.length;i++){
                index[i]=i;
            }
            return mergeSort(nums,0,nums.length-1);
        }
        public int mergeSort(int[]nums,int left,int right){
            if(left>=right)return 0;
            int mid=(left+right)/2;
            mergeSort(nums,left,mid);
            mergeSort(nums,mid+1,right);
            int[]tmp=new int[right-left+1];
            int[]index2=new int[right-left+1];
            int cur1=left;
            int cur2=mid+1;
            int k=0;

            while(cur1<=mid&&cur2<=right){
                while(cur2<=right&&(long)nums[cur1]<=(long)2*nums[cur2])cur2++;
                if(cur2>right)break;
                    ret+=right-cur2+1;
                    cur1++;}
            cur1=left;
            cur2=mid+1;


            while(cur1<=mid&&cur2<=right){
                if(nums[cur1]>nums[cur2]){
                    index2[k]=index[cur1];
                    tmp[k++]=nums[cur1++];
                }else{
                    index2[k]=index[cur2];
                    tmp[k++]=nums[cur2++];
                }
            }

            while(cur1<=mid){index2[k]=index[cur1];tmp[k++]=nums[cur1++];}
            while(cur2<=right){index2[k]=index[cur2];tmp[k++]=nums[cur2++];}
            k=0;
            for(int i=left;i<=right;i++){
                index[i]=index2[k];
                nums[i]=tmp[k++];
            }
            return ret;
        }
}
相关推荐
网易独家音乐人Mike Zhou2 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
Swift社区5 小时前
LeetCode - #139 单词拆分
算法·leetcode·职场和发展
Kent_J_Truman6 小时前
greater<>() 、less<>()及运算符 < 重载在排序和堆中的使用
算法
IT 青年6 小时前
数据结构 (1)基本概念和术语
数据结构·算法
Dong雨7 小时前
力扣hot100-->栈/单调栈
算法·leetcode·职场和发展
SoraLuna7 小时前
「Mac玩转仓颉内测版24」基础篇4 - 浮点类型详解
开发语言·算法·macos·cangjie
liujjjiyun7 小时前
小R的随机播放顺序
数据结构·c++·算法
¥ 多多¥7 小时前
c++中mystring运算符重载
开发语言·c++·算法
trueEve8 小时前
SQL,力扣题目1369,获取最近第二次的活动
算法·leetcode·职场和发展
天若有情6738 小时前
c++框架设计展示---提高开发效率!
java·c++·算法