当前位置: 首页 > news >正文

分治-归并排序-逆序对问题

目录

1.升序(以右边的合并组为基准)

2.降序(以左边的合并组为基准)

 3.逆对序--固定下表


1.升序(以右边的合并组为基准)

找出左边有多少个数比我(nums[right])大

  • 应该在每一次合并之前,进行逆序对查找
  • 每一个该合并的组都是按升序排列,所以当nums[left]<nums[right]时,应该left++,因为都是升序,所以当nums[left]>nums[right],right++时,left从当前位置不动。

class Solution {
public:
    vector<int> ret;
    int vim=0;
    int reversePairs(vector<int>& record) {
        ret.resize(record.size());
        mergesort(record,0,record.size()-1);
        return vim;
    }
    void merge(vector<int>&nums,int low,int high,int mid)
    {
        int left=low,right=mid+1, i=0;
        while(left<=mid&&right<=high)
        {
             if(nums[left]<=nums[right]) ret[i++]=nums[left++];
            else  
            {
                ret[i++]=nums[right++];
                vim+=(mid+1-left);
            }
        }
        while(left<=mid) ret[i++]=nums[left++];
        while(right<=high) ret[i++]=nums[right++];
        for(int i=0;i<high-low+1;i++)
        {
            nums[i+low]=ret[i];
        }
    }
    void mergesort(vector<int>&nums,int low,int high)
    {
        if(low>=high) return;
        int mid=(low+high)/2;
        mergesort(nums,low,mid);
        mergesort(nums,mid+1,high);
        merge(nums,low,high,mid);
        
    }
};

2.降序(以左边的合并组为基准)

 找出多少个数比我小

 合并过程:

 

class Solution {
public:
    vector<int> ret;
    int vim=0;
    int reversePairs(vector<int>& record) {
        ret.resize(record.size());
        mergesort(record,0,record.size()-1);
        return vim;
    }
    void merge(vector<int>&nums,int low,int high,int mid)
    {
        int left=low,right=mid+1, i=0;
        while(left<=mid&&right<=high)
        {
             if(nums[left]>nums[right]) 
             {
                vim+=(high-right+1);
                ret[i++]=nums[left++];
             }
            else  
            {
                ret[i++]=nums[right++];
            }
        }
        while(left<=mid) ret[i++]=nums[left++];
        while(right<=high) ret[i++]=nums[right++];
        for(int i=0;i<high-low+1;i++)
        {
            nums[i+low]=ret[i];
        }
    }
    void mergesort(vector<int>&nums,int low,int high)
    {
        if(low>=high) return;
        int mid=(low+high)/2;
        mergesort(nums,low,mid);
        mergesort(nums,mid+1,high);
        merge(nums,low,high,mid);
        
    }
};

 对比:

降序升序

void merge(vector<int>&nums,int low,int high,int mid)
    {
        int left=low,right=mid+1, i=0;
        while(left<=mid&&right<=high)
        {
             if(nums[left]>nums[right]) 
             {
                vim+=(high-right+1);
                ret[i++]=nums[left++];
             }
            else  
             ret[i++]=nums[right++];

}
        while(left<=mid) ret[i++]=nums[left++];
        while(right<=high) ret[i++]=nums[right++];
        for(int i=0;i<high-low+1;i++)
        {
            nums[i+low]=ret[i];
        }
    }

 void merge(vector<int>&nums,int low,int high,int mid)
    {
        int left=low,right=mid+1, i=0;
        while(left<=mid&&right<=high)
        {
             if(nums[left]<=nums[right])                 ret[i++]=nums[left++];
            else  
            {
                ret[i++]=nums[right++];
                vim+=(mid+1-left);
            }

        }
        while(left<=mid) ret[i++]=nums[left++];
        while(right<=high) ret[i++]=nums[right++];
        for(int i=0;i<high-low+1;i++)
        {
            nums[i+low]=ret[i];
        }
    }

 3.逆对序--固定下表

增加一个下表数据,和交换下表数组,当交换数组发生数据交换时,交换下表数组也要发生数据交换

 

class Solution {
public:
    vector<int> tmp;    // 临时数据数组
    vector<int> count;  // 结果数组
    vector<int> index;  // 原始索引数组
    vector<int> tmpIdx; // 临时索引数组

    vector<int> countSmaller(vector<int>& nums) {
        int n = nums.size();
        tmp.resize(n);
        count.resize(n, 0);
        index.resize(n);
        tmpIdx.resize(n);
        // 初始化原始索引
        for(int i = 0; i < n; ++i) index[i] = i;
        mergesort(nums, 0, n-1);
        return count;
    }

    void mergesort(vector<int>& nums, int low, int high) {
        if(low >= high) return;
        int mid = low + (high - low)/2; // 防溢出
        mergesort(nums, low, mid);
        mergesort(nums, mid+1, high);
        merge(nums, low, mid, high);
    }

    void merge(vector<int>& nums, int low, int mid, int high) {
        int left = low, right = mid+1, i = 0;

        // 合并并统计
        while(left <= mid && right <= high) {
            if(nums[left] > nums[right]) {
                // 右元素更小:存入临时数组并计数
                tmp[i] = nums[left];
                tmpIdx[i] = index[left]; // 记录原始索引
                count[index[left]]+=high-right+1;
                left++;
                i++;
            } else {
                // 左元素更大或等于:累加已处理的右元素数
                tmp[i] = nums[right];
                tmpIdx[i] = index[right]; // 记录原始索引
                right++;
                i++;
            }
        }

        // 处理剩余左半部分(补充统计)
        while(left <= mid) {
            tmp[i] = nums[left];
            tmpIdx[i] = index[left];
            left++;
            i++;
        }

        // 处理剩余右半部分(无需统计)
        while(right <= high) {
            tmp[i] = nums[right];
            tmpIdx[i] = index[right];
            right++;
            i++;
        }

        // 写回原数组并更新索引
        for(int id = 0; id < i; ++id) {
            nums[low + id] = tmp[id];
            index[low + id] = tmpIdx[id]; // 正确传递原始索引
        }
    }
};

http://www.dtcms.com/a/113585.html

相关文章:

  • 计算机视觉图像处理基础系列:滤波、边缘检测与形态学操作
  • 小迪安全110-tp框架,版本缺陷,不安全写法,路由访问,利用链
  • Android使用OpenGL和MediaCodec渲染视频
  • AI浪潮下,“内容创作平台”能否借势实现内容价值跃升?
  • Turtle图形化编程知识点汇总:让编程更有趣
  • IDEA 2024.3.5 中修改 web.xml 的 Servlet 版本(比如从 4.0 修改为 5.0)
  • I.MX6ULL开发板与linux互传文件的方法--NFS,SCP,mount
  • AbstractBeanFactory
  • 基于SSM的车辆管理系统的设计与实现(代码+数据库+LW)
  • kd树和球树
  • Java中使用OpenCV实现怀旧滤镜时遇到的UnsatisfiedLinkError问题及解决方案
  • 一文读懂 MCP!
  • chromadb
  • Swift 扩展
  • 微服务架构与中台的关系
  • 高通camx ThreadManager
  • 【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 的未来:从微服务到云原生的演进
  • Hyperlane框架:下一代高性能Rust Web框架 [特殊字符]
  • 学习笔记,DbContext context 对象是保存了所有用户对象吗
  • ring语言,使用vscode编辑器
  • AtCoder Beginner Contest 399 D,F 题解
  • 对迭代器模式的理解
  • Arduino示例代码讲解:Knock Sensor 敲击感知器
  • 每日一题(小白)模拟娱乐篇14
  • BN测试和训练时有什么不同, 在测试时怎么使用?
  • 【C++项目】从零实现RPC框架「四」:业务层实现与项目使用
  • 【51单片机】2-7【I/O口】点亮数码管
  • 线程池的工作原理
  • 线代[12]|《高等几何》陈绍菱(1984.9)(文末有对三大空间的分析及一个合格数学系毕业生的要求)
  • Python 语法学习 1(类比 java 学习)-附Python 中 self