分治归并,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;
        }
}
相关推荐
AI莫大猫41 分钟前
(6)YOLOv4算法基本原理以及和YOLOv3 的差异
算法·yolo
taoyong00144 分钟前
代码随想录算法训练营第十一天-239.滑动窗口最大值
c++·算法
Uu_05kkq1 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
清梦20202 小时前
经典问题---跳跃游戏II(贪心算法)
算法·游戏·贪心算法
Dream_Snowar3 小时前
速通Python 第四节——函数
开发语言·python·算法
Altair澳汰尔3 小时前
数据分析和AI丨知识图谱,AI革命中数据集成和模型构建的关键推动者
人工智能·算法·机器学习·数据分析·知识图谱
A懿轩A3 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
Python机器学习AI3 小时前
分类模型的预测概率解读:3D概率分布可视化的直观呈现
算法·机器学习·分类
吕小明么4 小时前
OpenAI o3 “震撼” 发布后回归技术本身的审视与进一步思考
人工智能·深度学习·算法·aigc·agi
1 9 J4 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法