分治-归并排序

在这里插入图片描述

文章目录

    • 🌞315. 计算右侧小于当前元素的个数
      • 🌈1. 题目
      • ⛅2. 算法原理
      • 🪐3. 代码实现
    • 🌕493. 翻转对
      • 🌠1. 题目
      • ⭐2. 算法原理
      • 🌟3. 代码实现

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

🌈1. 题目

题目链接:315. 计算右侧小于当前元素的个数

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

示例 1:

输入:nums = [5,2,6,1]
输出:[2,1,1,0] 
解释:
5 的右侧有 2 个更小的元素 (2 和 1)
2 的右侧仅有 1 个更小的元素 (1)
6 的右侧有 1 个更小的元素 (1)
1 的右侧有 0 个更小的元素

示例 2:

输入:nums = [-1]
输出:[0]

示例 3:

输入:nums = [-1,-1]
输出:[0,0]

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104

⛅2. 算法原理

这题要找的是当前元素的后面,有多少个比它小的元素。

解法一:暴力枚举

固定一个原始,然后往后扫码,看看有多少个元素是小于它的,时间复杂度为O(N2),题目的数据量较大,这个复杂度肯定会超时。

解法二:分治

如图:

image-20231203151009955

由于这里是要返回一个数组,返回的数组要对应原始数组的下标,所以这里我们要找到当前元素的原始下标是多少。

这里找映射,一般采用的就是哈希表,但是如果这里有重复的元素,哈希表就失效了。我们可采取一个数组和原始的数组原始绑定

nums: [15,17,20,23,12,3]
index:[ 0, 1, 2, 3, 4,5]

🪐3. 代码实现

class Solution {
    vector<int> ret;
    vector<int> index;
    int tmpNums[500001];
    int tmpIndex[500001];
public:
    vector<int> countSmaller(vector<int>& nums)
    {
        int n = nums.size();
        ret.resize(n);
        index.resize(n);
        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;
        int mid = (left + right) >> 1;
        mergeSort(nums, left, mid);
        mergeSort(nums, mid+1, right);

        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++];
            }
        }
        while(cur1 <= mid)
        {
            tmpNums[i] = nums[cur1];
            tmpIndex[i++] = index[cur1++];
        }
        while(cur2 <= right)
        {
            tmpNums[i] = nums[cur2];
            tmpIndex[i++] = index[cur2++];
        }

        for(int i=left; i<=right; i++)
        {
            nums[i] = tmpNums[i-left];
            index[i] = tmpIndex[i-left];
        }
    }
};

运行结果:

image-20231203151941356

🌕493. 翻转对

🌠1. 题目

题目链接:493. 翻转对

给定一个数组 nums ,如果 i < jnums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对

你需要返回给定数组中的重要翻转对的数量。

示例 1:

输入: [1,3,2,3,1]
输出: 2

示例 2:

输入: [2,4,3,5,1]
输出: 3

注意:

  1. 给定数组的长度不会超过50000
  2. 输入数组中的所有数字都在32位整数的表示范围内。

⭐2. 算法原理

这题也相当于是找逆序对,只不过它要找的是小于它2倍的对数。

解法一:暴力枚举

固定一个数,依此往后枚举,统计总共有多少对,时间复杂度为O(N2),应该会超时

解法二:分治

这里和归并排序是有一定出入的,归并排序是一比一比较的,但这里要比较的是前面的元素大于后面元素的两倍。

还是两种策略:

  1. 计算当前元素后面,有多少元素的两倍小于当前元素(降序
    利用单调性,采用同向双指针,先固定cur1,找nums[cur1] > num[cur2]*2
    image-20231203154228096
  2. 计算当前元素的前面,有多少元素的两倍大于当前元素(升序
    同理,先固定cur2,找nums[cur1] > nums[cur2]*2

🌟3. 代码实现

class Solution {
    int tmp[50001];
public:
    int reversePairs(vector<int>& nums)
    {
        int n = nums.size();
        return mergeSort(nums,0,n-1);
    }

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

        int ret = 0;
        int mid = (left+right)>>1;
        ret += mergeSort(nums, left, mid);
        ret += mergeSort(nums, mid+1, right);

        int cur1 = left,
        cur2 = mid +1,
        i = left;
        while(cur2 <= right)
        {
            while(cur1 <= mid && nums[cur2] >= nums[cur1]/2.0)   cur1++;
            if(cur1 > mid)  break;
            ret += mid - cur1 + 1;
            cur2++; 
        }
        //合并
        cur1 = left,
        cur2 = mid+1,
        i = left;
        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 i=left; i<=right; i++)  nums[i] = tmp[i];
        return ret;
    }
};

运行结果:

image-20231203162247354

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Matlab数学建模详解之发电机的最佳调度实现

&#x1f517; 运行环境&#xff1a;Matlab、Python &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&am…

String类 ---java

目录 一. 常用的字符串的构造 二. 字符串的源代码 三. 字符串比较 1. 是不能比较字符串的值的 ​编辑 2.比较两个字符串 --- compareTo() 3. 忽略大小写比较 ---compareToIgnoreCase() 四. 字符串转化 1. 数字转字符串 valueOf() 2. 字符串转数字 3. 小写转大写 to…

树莓派多串口通信

树莓派多串口通信 串口配置串口通信函数分析串口通信示例代码 参考博文1&#xff1a;树莓派 4 UART 多串口配置通信参考博文2&#xff1a;树莓派wiringPi库详解关于树莓派相关其他环境配置可参考&#xff1a;快速上手树莓派关于wiringPi库初始化与IO口开发可参考&#xff1a;树…

OpenLayer库的学习入门总结

前言&#xff1a; 作者跟随视频学习ol库的调用与功能实现&#xff0c;进行初步总结与回顾。 声明&#xff1a;参考新中地的文档&#xff0c;进行作者日后复习再次学习的简化。 1、WebGIS简介 GIS的核心概念 GIS&#xff08;Geographic Information System&#xff09;是一…

第 374 场 LeetCode 周赛题解

A 找出峰值 枚举 class Solution { public:vector<int> findPeaks(vector<int> &mountain) {int n mountain.size();vector<int> res;for (int i 1; i < n - 1; i)if (mountain[i] > mountain[i - 1] && mountain[i] > mountain[i 1…

中断方式的数据接收2

Echo实验 回忆之前的实验因为数据处理的过程可以瞬间完成所以可以把数据处理的操作放在中断服务函数中执行 但是数据处理要是时间过长就将数据缓存处理 当使用中断方式接收数据的时候 一般有两种方式 数据处理的时间较短可放在中断服务函数内处理&#xff08;就地处理&#…

【Linux--进程】

目录 一、基本概念1.1描述进程-PCB1.2task_struct中内容分类 二、了解进程2.1查看进程2.2通过系统调用获取进程标识符 三、fork创建进程3.1fork()函数3.2写时拷贝 四、进程的状态4.1操作系统学科里的进程状态&#xff08;运行、阻塞、挂起&#xff09;4.具体的Linux状态是如何维…

LinuxBasicsForHackers笔记 --常用Linux命令

在终端中修改用户密码命令&#xff1a;passwd Linux的文件系统是逻辑文件系统。 Linux基本命令 pwd – print working directory. 返回你当前所在目录结构中的位置。 whoami – 查看您当前登录的用户身份。 cd – change directory. 从终端更改目录。 cd / – 移动到根目录…

大数据实战项目_电商推荐系统

一、 项目介绍 HadoopSpark (Python)Scala SparkSQLSparkStreaming MongoDB Redis Kafka Flume ( SpringMVC vue) 1 项目介绍 1.1 项目系统架构 项目以推荐系统建设领域知名的经过修改过的中文亚马逊电商数据集作为依托&#xff0c;以某电商网站真实业务数据架构为基…

openGauss学习笔记-139 openGauss 数据库运维-例行维护-检查应用连接数

文章目录 openGauss学习笔记-139 openGauss 数据库运维-例行维护-检查应用连接数139.1 操作步骤139.2 异常处理 openGauss学习笔记-139 openGauss 数据库运维-例行维护-检查应用连接数 如果应用程序与数据库的连接数超过最大值&#xff0c;则新的连接无法建立。建议每天检查连…

淘宝商家店铺注册流程

如果本身已经有淘宝账号了&#xff0c;直接从第三步骤&#xff1a;创建店铺开始就可以了。一、注册淘宝账号、支付宝账号 首先,如果你有买家账号,是可以直接拿来开店的&#xff0c;不用单独在注册淘宝账号开店。 注意事项: 1:淘宝账号注册后,不能修改,如果会员名有写错情况&a…

【多线程】-- 10线程同步synchronized方法/块

多线程 6 线程同步 同步方法 由于我们可以通过private关键字来保证数据对象只能被方法访问&#xff0c;所以我们只需要针对方法提出一套机制&#xff0c;这套机制就是synchronized关键字&#xff0c;它包括以下两种用法&#xff1a; ​ synchronized方法和synchronized块 …

初始化 Clouder Manager 数据库报错Unable to find JDBC driver for database type: MySQL

CDH部署初始化 Clouder Manager 数据库报错。 解决方法&#xff1a; 把mysql驱动放到 /usr/share/java/目录下面(没有的新建&#xff09;&#xff0c;驱动名称也要修改为mysql-connector-java.jar 再次执行后成功&#xff1a; sudo /opt/cloudera/cm/schema/scm_prepare_data…

javaweb mybatis(手动jar包)

基础&#xff1a;https://blog.csdn.net/qq_67832732/article/details/134764134 条件查询 在映射文件的SQL配置中配置参数 使用parameterType来指定参数类型 使用#{参数名}来接收参数的值 parameterType"string" 表示sql语句需要一个参数&#xff0c;类型为字符…

串行口的工作原理及应用

前言 对最近串行口的学习进行一下总结。 参考链接 【51单片机】串口通信 - 知乎 (zhihu.com) LED数码管的静态显示与动态显示&#xff08;KeilProteus&#xff09;_proteus数码管显示-CSDN博客 定时器/计数器的应用-CSDN博客 74ls164_百度百科 (baidu.com) 74ls165中文资…

Kafka 的特点和优势

Apache Kafka 作为一款分布式流处理平台&#xff0c;以其独特的特点和卓越的优势成为实时数据处理领域的瑰宝。本文将深入研究 Kafka 的各项特点和优势&#xff0c;并通过详实的示例代码展示其在不同场景下的强大应用。 高吞吐量和水平扩展 Kafka 的设计注重高吞吐量和水平扩…

使用外部编辑器编辑执行MAXScript代码的方法

如何使用外部编辑器编辑执行MAXScript代码&#xff1f;这里我们要借助一个3dMax插件程序MXSCOM&#xff0c;MXSCOM允许从外部代码编辑器编辑和执行3ds Max MaxScript和Python文件。 2005年&#xff0c;Simon Feltman发布了第一个MXSCOM&#xff0c;这是一个小型的Visual Basic …

【Delphi】实现彩色日志显示框

目录 一、前言 二、实现方法 1. 第一步 2. 第二步 3. 第三步 三、主程序代码 四、下载 1. 可执行程序 2. 程序源代码 一、前言 在用Delphi做日常开发的时候&#xff0c;经常需要显示程序运行的日志&#xff0c;一般我们会使用TMemo&#xff0c;使用起来简单&#xff0c…

根据关键词写作文章的软件,根据标题写作文章的工具

在当今信息化时代&#xff0c;人工智能技术的飞速发展&#xff0c;智能AI写作工具逐渐成为文案创作者的得力助手。这些工具不仅能够根据标题迅速生成文章&#xff0c;而且在提高创作效率的同时&#xff0c;也为我们节省了大量时间和精力。 人工智能的基本原理&#xff1a;人工智…

Python遥感开发之快速判断TIF数据为空

Python遥感开发之快速判断TIF数据为空 前言&#xff1a;介绍一下如何使用python下的gdal读取tif数据的时候&#xff0c;快速判断该tif数据是否为空&#xff0c;如果为空的话就把当前的tif删掉。 如图所示&#xff0c;通过arcgis查看箭头指向的为空值。 仅通过文件的大小无法判…