专题八_分治-归并

news2024/9/20 14:58:20

目录

912. 排序数组

解析

题解

LCR 170. 交易逆序对的总数(数组中的逆序对)

解析

题解

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

解析

题解

493. 翻转对

解析

题解


912. 排序数组

912. 排序数组

 

解析

题解

1.局部临时数组

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        // 49.专题八_分治-归并_归并排序_C++
        mergeSort(nums, 0, nums.size() - 1);
        return nums;
    }
    void mergeSort(vector<int>& nums, int left, int right)
    {
        if (left >= right) return;

        // 1.选择中间点划分区间
        int mid = (right - left) / 2 + left;
        // [left, mid] [mid + 1, right]

        // 2.把左右区间排序
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);

        // 3.合并两个有序数组
        vector<int> tmp(right - left + 1);
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur1 <= mid && cur2 <= right)
            tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];
        // 4.处理没有遍历完的数组
        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= right) tmp[i++] = nums[cur2++];

        // 5.还原
        for (int i = left; i <= right; ++i)
            nums[i] = tmp[i - left];
    }
};

2.全局临时数组

class Solution {
public:
    vector<int> tmp;
    vector<int> sortArray(vector<int>& nums) {
        // 49.专题八_分治-归并_归并排序_C++
        tmp.resize(nums.size());
        mergeSort(nums, 0, nums.size() - 1);
        return nums;
    }
    void mergeSort(vector<int>& nums, int left, int right)
    {
        if (left >= right) return;

        // 1.选择中间点划分区间
        int mid = (right - left) / 2 + left;
        // [left, mid] [mid + 1, right]

        // 2.把左右区间排序
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);

        // 3.合并两个有序数组
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur1 <= mid && cur2 <= right)
            tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];
        // 4.处理没有遍历完的数组
        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= right) tmp[i++] = nums[cur2++];

        // 5.还原
        for (int i = left; i <= right; ++i)
            nums[i] = tmp[i - left];
    }
};

 

LCR 170. 交易逆序对的总数(数组中的逆序对)

LCR 170. 交易逆序对的总数

 

解析

题解

1.升序

class Solution {
public:
    int tmp[50001] = {0};
    int reversePairs(vector<int>& record) {
        // 50.专题八_分治-归并_数组中的逆序对_C++
        // 1.升序
        return mergeSort(record, 0, record.size() - 1);
    }
    int mergeSort(vector<int>& record, int left, int right)
    {
        if (left >= right) return 0;

        int ret = 0;
        // 1. 找中间点, 将数组分成两部分
        int mid =  (right - left) / 2 + left;
        // [left, mid] [mid + 1, right]

        // 2. 左边的个数 + 排序 + 右边的个数 + 排序
        ret += mergeSort(record, left, mid);
        ret += mergeSort(record, mid + 1, right);

        // 3. 一左一右的个数
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur1 <= mid && cur2 <= right)
        {
            if (record[cur1] <= record[cur2])
            {
                tmp[i++] = record[cur1++];
            }
            else 
            {
                ret += mid - cur1 + 1;
                tmp[i++] = record[cur2++];
            }
        }
        // 4.处理一下排序
        while(cur1 <= mid) tmp[i++] = record[cur1++];
        while(cur2 <= right) tmp[i++] = record[cur2++];
        for(int j = left; j <= right; ++j)
            record[j] = tmp[j - left];
        return ret;
    }
};

2.降序

class Solution {
public:
    int tmp[50001] = {0};
    int reversePairs(vector<int>& record) {
        // 50.专题八_分治-归并_数组中的逆序对_C++
        // 1.降序
        return mergeSort(record, 0, record.size() - 1);
    }
    int mergeSort(vector<int>& record, int left, int right)
    {
        if (left >= right) return 0;

        int ret = 0;
        // 1. 找中间点, 将数组分成两部分
        int mid =  (right - left) / 2 + left;
        // [left, mid] [mid + 1, right]

        // 2. 左边的个数 + 排序 + 右边的个数 + 排序
        ret += mergeSort(record, left, mid);
        ret += mergeSort(record, mid + 1, right);

        // 3. 一左一右的个数
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur1 <= mid && cur2 <= right)
        {
            if (record[cur1] <= record[cur2])
            {
                tmp[i++] = record[cur2++];
            }
            else 
            {
                ret += right - cur2 + 1;
                tmp[i++] = record[cur1++];
            }
        }
        // 4.处理一下排序
        while(cur1 <= mid) tmp[i++] = record[cur1++];
        while(cur2 <= right) tmp[i++] = record[cur2++];
        for(int j = left; j <= right; ++j)
            record[j] = tmp[j - left];
        return ret;
    }
};

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

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

解析

题解

class Solution {
public:
    vector<int> ret;
    vector<int> index; // 记录 nums 中当前元素的原始下标
    int tmpNums[500010];
    int tmpIndex[500010];
    vector<int> countSmaller(vector<int>& nums) {
        // 51.专题八_分治-归并_计算右侧小于当前元素的个数_C++
        int n = nums.size();
        ret.resize(n);
        index.resize(n);

        // 初始一下 index 数组
        for (int i = 0; i < n; ++i)
            index[i] = i;
        mergeSort(nums, 0, n - 1);
        return ret;
    }

    void mergeSort(vector<int>& nums, int left, int right)
    {
        if (left >= right) return;

        // 1.根据中间元素,划分区间
        int mid = (right - left) / 2 + left;
        // [left, mid] [mid + 1, right]

        // 2.先处理左右两部分
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);

        // 3.处理一左一右的情况
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur1 <= mid && cur2 <= right)
        {
            if (nums[cur1] <= nums[cur2])
            {
                tmpNums[i] = nums[cur2];
                tmpIndex[i++] = index[cur2++];
            }
            else
            {
                ret[index[cur1]] += right - cur2 + 1; // 重点
                tmpNums[i] = nums[cur1];
                tmpIndex[i++] = index[cur1++];
            }
        }

        // 4.处理剩下的排序过程
        while(cur1 <= mid)
        {
            tmpNums[i] = nums[cur1];
            tmpIndex[i++] = index[cur1++];
        }
        while(cur2 <= right)
        {
            tmpNums[i] = nums[cur2];
            tmpIndex[i++] = index[cur2++];
        }
        for (int j = left; j <= right; ++j)
        {
            nums[j] = tmpNums[j - left];
            index[j] = tmpIndex[j - left];
        }
    }
};

493. 翻转对

493. 翻转对

解析

题解

1.降序

class Solution {
public:
    int tmp[50010];
    int reversePairs(vector<int>& nums) {
        // 52.专题八_分治-归并_翻转对_C++
        // 1.降序
        return mergeSort(nums, 0, nums.size() - 1);
    }

    int mergeSort(vector<int>& nums, int left, int right)
    {
        if (left >= right) return 0;

        int ret = 0;
        // 1.先根据中间元素划分区间
        int mid = (right - left) / 2 + left;
        // [left, mid] [mid + 1, right]

        // 2.先计算左右两侧的翻转对
        ret += mergeSort(nums, left, mid);
        ret += mergeSort(nums, mid + 1, right);

        // 3.先计算翻转对的数量
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur1 <= mid)
        {
            while(cur2 <= right && nums[cur2] >= nums[cur1] / 2.0) cur2++;
            if (cur2 > right) break;
            ret += right - cur2 + 1;
            cur1++;
        }

        // 4.合并两个有序数组
        cur1 = left, cur2 = mid + 1;
        while(cur1 <= mid && cur2 <= right)
            tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur2++] : nums[cur1++];
        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= right) tmp[i++] = nums[cur2++];

        for (int j = left; j <= right; ++j)
            nums[j] = tmp[j - left];
        return ret;
    }
};

2.升序

class Solution {
public:
    int tmp[50010];
    int reversePairs(vector<int>& nums) {
        // 52.专题八_分治-归并_翻转对_C++
        // 1.升序
        return mergeSort(nums, 0, nums.size() - 1);
    }

    int mergeSort(vector<int>& nums, int left, int right)
    {
        if (left >= right) return 0;

        int ret = 0;
        // 1.先根据中间元素划分区间
        int mid = (right - left) / 2 + left;
        // [left, mid] [mid + 1, right]

        // 2.先计算左右两侧的翻转对
        ret += mergeSort(nums, left, mid);
        ret += mergeSort(nums, mid + 1, right);

        // 3.先计算翻转对的数量
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur2 <= right)
        {
            while(cur1 <= mid && nums[cur2] >= nums[cur1] / 2.0) cur1++;
            if (cur1 > mid) break;
            ret += mid - cur1 + 1;
            cur2++;
        }

        // 4.合并两个有序数组
        cur1 = left, cur2 = mid + 1;
        while(cur1 <= mid && cur2 <= right)
            tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];
        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= right) tmp[i++] = nums[cur2++];

        for (int j = left; j <= right; ++j)
            nums[j] = tmp[j - left];
        return ret;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1966170.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

换地不换IP?揭秘微博IP地址的奥秘

在这个信息飞速传递的时代&#xff0c;社交媒体成为我们生活中不可或缺的一部分。微博&#xff0c;作为其中的佼佼者&#xff0c;不仅是我们获取资讯的重要渠道&#xff0c;也是展现自我、分享生活的重要平台。然而&#xff0c;你有没有遇到过这样的情况&#xff1a;明明已经换…

智能相机背后的图像防抖(IS)技术介绍

智能相机背后的图像防抖(IS)技术介绍 在现代摄影和视频拍摄中&#xff0c;防抖技术已成为必不可少的一部分。随着智能手机、相机和其他成像设备的普及&#xff0c;防抖技术的需求也越来越高。本文将详细介绍几种主要的防抖技术&#xff0c;包括光学防抖&#xff08;OIS&#x…

【Redis 初阶】客户端(C++ 使用样例列表)

一、编写 helloworld 需要先使用 redis-plus-plus 连接一下 Redis 服务器&#xff0c;再使用 ping 命令检测连通性。 1、Makefile Redis 库最多可以支持到 C17 版本。&#xff08;如果是用 Centos&#xff0c;需要注意 gcc/g 的版本&#xff0c;看是否支持 C17。不支持的话&a…

【第五节】python异常处理

目录 一、python中的异常用法 1.1 try-except 1.2 异常处理流程&#xff1a; 1.3 try-finally 1.4 使用except是否指定异常 二、异常的参数 三、自定义异常 四、常见的异常列举 一、python中的异常用法 异常是指程序运行过程中出现的非正常状态。在Python编程中&#x…

线程的创建Linux下

进程的创建&#xff1a;第一个参数通常传递一个pthread_t 的地址&#xff0c;第二个参数为线程的属性&#xff0c;第三个参数为函数指针&#xff0c;是子线程要做的事情。arg是函数指针所对应函数的参数。 sleep主要是为了等待子线程退出&#xff0c;因为当主线程退出时&#x…

WebSocket connection to ‘ws://x.x.x.x:8080/ws‘ failed:报错

vue.config.js中进行修改 添加 devServer: { Proxy: {ws:false }}

Flink-StarRocks详解:第二部分(第52天)

文章目录 前言2. 表设计2.1 StarRocks表设计2.1.1 列式存储2.1.2 索引2.1.3 加速处理2.1.3.1 预先聚合2.1.3.2 分区分桶2.1.3.3 物化视图2.1.3.4 列级索引 2.2 数据模型2.2.1 明细模型2.2.1.1 适用场景2.2.1.2 创建表2.2.1.3 使用说明 2.2.2 聚合模型2.2.2.1 适用场景2.2.2.2 原…

[C++] vector对比list deque的引出

文章目录 list与vector的对比双端队列dequedeque的特性deque的底层实现原理内存结构块表&#xff08;Block Array&#xff09;块&#xff08;Block&#xff09; 插入与删除两端插入两端删除 随机访问如何计算位置 迭代器设计 总结 list与vector的对比 vector与list都是STL中非…

实战AR增强现实【OpenCV+Ogre】

作为一份小小的礼物&#xff0c;我想向你展示借助 Ogre 和 OpenCV 自己制作增强现实变得多么容易。你应该知道&#xff0c;除了图形之外&#xff0c;我的另一个兴趣是计算机视觉。 演示将不依赖于 ARCore 或 ARKit 等专有解决方案 - 所有这些都将使用开源代码完成&#xff0c;…

【ROS2】 默认的DDS通信中间件替换为Eclipse Cyclone_DDS (DDS配置方法)

ROS2替换中间件为Cyclone_DDS 1.一些介绍&#xff1a;&#xff09;2.不同DDS的RMW实现3.默认的FastDDS替换为Cyclone DDSi.安装依赖ii.编译 cyclone-dds 4.配置网络 1.一些介绍&#xff1a;&#xff09; 上一篇我们探讨了ros1和ros2编写launch的区别 【ROS2】launch启动文件编…

相机外参矩阵

在上一篇文章中&#xff0c;我们学习了如何将相机矩阵分解为内参矩阵和外参矩阵的乘积。在接下来的两篇文章中&#xff0c;我们将更详细地探讨外参矩阵和内参矩阵。首先&#xff0c;我们将探讨查看外参矩阵的各种方式&#xff0c;并在最后进行交互式演示。 SDT工具推荐&#xf…

程序员必知必懂运维技术概念

引言 随着互联网和云计算的迅速发展&#xff0c;传统的单体架构逐渐被微服务架构所取代。这一变化带来了许多新的挑战&#xff0c;如环境一致性、应用的可移植性、服务的扩展性、服务间通信的管理以及安全性等。为了解决这些问题&#xff0c;业界开发了许多工具和技术&#xf…

SPSSAU | Adaboost模型原理及案例实操

AdaBoost&#xff08;Adaptive Boosting&#xff09;算法的核心思想是将多个弱分类器组合成一个强分类器。其算法步骤如下&#xff1a; 第一&#xff1a;初始化权重&#xff0c;为每个训练样本分配相等的初始权重&#xff1b; 第二&#xff1a;训练弱分类器&#xff0c;根据当…

如何做OLED屏幕安装方案

制定OLED屏幕安装方案时&#xff0c;需要综合考虑多个方面&#xff0c;包括安装环境、屏幕尺寸、支架选择、电源与信号连接、调试与测试等。以下是一个详细的OLED屏幕安装方案&#xff1a; 一、前期准备 确定安装位置&#xff1a; 根据使用需求和环境条件&#xff0c;选择一个…

基于FPGA的以太网设计(4)----详解PHY的使用(以YT8531为例)

目录 1、前言 2、如何了解PHY芯片? 2.1、总览 2.2、管脚 2.3、编码 2.4、自协商 2.5、环回模式 2.6、睡眠模式 2.7、复位 2.8、PHY地址 3、PHY芯片的寄存器配置 3.1、Basic Control Register (0x00) 3.2、Basic StatusRegister (0x01) 3.3、PHY Specific Status…

重生了,这一世 我一定要学会服务器 只因………

你好,我是Qiuner. 为帮助别人少走弯路和记录自己编程学习过程而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​ gitee https://gitee.com/Qiuner &#x1f339; 如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 &#x1f604; (^ ~ ^) 想看更多 那就点个关注吧 我…

IT运维管理与ITSM:理论与实践

IT运维管理和IT服务管理&#xff08;ITSM&#xff09;在现代企业信息化过程中占据着举足轻重的地位。它们不仅是确保IT系统稳定运行和业务连续性的关键&#xff0c;还是推动企业数字化转型、提升竞争力的重要力量。本文将结合《IT运维管理和ITSM》文档的内容&#xff0c;深入探…

【C++/STL】:哈希的应用 -- 位图布隆过滤器

目录 &#x1f680;&#x1f680;前言一&#xff0c;位图1. 位图的概念2. STL库中的位图3. 位图的设计4. 位图的模拟实现5. 位图的优缺点6. 位图相关考察题⽬ 二&#xff0c;布隆过滤器1. 布隆过滤器的概念2. 布隆过滤器的实现3. 布隆过滤器删除问题4. 布隆过滤器的优缺点 点击…

江森自控引入电子签,“碳”索智能建筑数字未来

近年来&#xff0c;伴随着科技的不断进步和市场领域的持续延伸&#xff0c;智能建筑已然成为建筑业科技升级的必经之路。 作为智能建筑领域的全球领导者&#xff0c;江森自控始终走在数字化变革前列&#xff0c;并在业内率先引入了电子合同&#xff0c;通过全流程线上进行的签…