分治-归并算法——LCR 170. 交易逆序对的总数

在这里插入图片描述

文章目录

    • 🌼0. 归并排序
    • 🌻1. 题目
    • 🌼2. 算法原理
    • 🌷3. 代码实现

🌼0. 归并排序

归并排序是典型的分治,将数组分成若干个子数组,数组两两比较,不是很清楚的,可以查看此篇文章——数据结构——七大排序

这里以力扣912. 排序数组为例:

class Solution {
    vector<int> tmp;
public:
    vector<int> sortArray(vector<int>& nums)
    {
        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;
        int mid = left + (right-left)/2;
        //[left,mid] [mid+1,right]
        mergeSort(nums,left,mid);
        mergeSort(nums,mid+1,right);
        //合并
        int i = 0,
            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 i = left; i <= right; i++)  nums[i] = tmp[i-left];

    }
};

🌻1. 题目

题目链接:LCR 170. 交易逆序对的总数

在股票交易中,如果前一天的股价高于后一天的股价,则可以认为存在一个「交易逆序对」。请设计一个程序,输入一段时间内的股票交易记录 record,返回其中存在的「交易逆序对」总数。

示例 1:

输入:record = [9, 7, 5, 4, 6]
输出:8
解释:交易中的逆序对为 (9, 7), (9, 5), (9, 4), (9, 6), (7, 5), (7, 4), (7, 6), (5, 4)

限制:

0 <= record.length <= 50000

🌼2. 算法原理

逆序对的意思就是,从数组中挑2个数,前面的数大于后面的数 且 前一个数的下标小于后一个数的下标,然后查看有几对

解法一:暴力枚举

固定一个数,找后面的区间,两层for循环即可,但是这个题目的等级是困难,对于力扣的题目等级划分,简单题基本可采用暴力解法,但是在中等及困难这两个等级,暴力解法大部分都是行不通的。

解法一:归并

如果要求整个数组的逆序对,我们可以将数组分为两部分,先求左边区域的逆序对,再求右边区域的逆序对,然后左边选一个、右边选一个,看看这样有多少个逆序对,这个的本质其实还是属于暴力枚举

image-20231203121210300

我们在此想法是再优化一下,即当左边区域挑选完毕之后,对左区域排序;右边区域挑选完毕之后,对右区域排序,然后再挑选,一左一右挑选完毕之后,再排一下序,这个过程就和归并排序的过程一样了。

为什么归并会快(升序为例)?

image-20231203122144250

我们固定一个数,要找出有多少个数比这个数大,在上图,我们看对于cur2,在左区间有多少个数比这个数大,这样就和归并排序完美契合,分3种情况:

  1. nums[cur1] <= nums[cur2]–>cur1++<=情况操作一样)
  2. nums[cur1] > nums[cur2] ,此时cur1后面的元素全部大于nums[cur2],然后就能直接统计出一大堆ret += mid - cur1 + 1cur2++

所以,这个时间复杂度就和归并排序的时间复杂度一模一样O(N*logN)

细节问题:

刚刚是以升序为例,如果采用降序,即找出该数之后,有多少个小于该数的元素

image-20231203124001251

🌷3. 代码实现

升序:

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

    int mergeSort(vector<int>& nums, int left, int right)
    {
        if(left >= right)   return 0;
        
        int ret = 0;
        int mid = (left + right) >> 1;
        
        //[left,mid]  [mid+1,right]
        //左边逆序对个数 排序
        //右边逆序对个数 排序
        ret += mergeSort(nums,left,mid);
        ret += mergeSort(nums,mid+1,right);

        //一左一右个数
        int cur1 = left,
            cur2 = mid+1,
            i = 0;
        while(cur1 <= mid && cur2 <= right)
        {
            if(nums[cur1] <= nums[cur2])    tmp[i++] = nums[cur1++];
            else
            {
                ret += mid - cur1 + 1;
                tmp[i++] = 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-left];
        return ret;
    }
};

降序:

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

    int mergeSort(vector<int>& nums, int left, int right)
    {
        if(left >= right)   return 0;
        
        int ret = 0;
        int mid = (left + right) >> 1;
        
        //[left,mid]  [mid+1,right]
        //左边逆序对个数 排序
        //右边逆序对个数 排序
        ret += mergeSort(nums,left,mid);
        ret += mergeSort(nums,mid+1,right);

        //一左一右个数
        int cur1 = left,
            cur2 = mid+1,
            i = 0;
        while(cur1 <= mid && cur2 <= right)
        {
            if(nums[cur1] <= nums[cur2])    tmp[i++] = nums[cur2++];
            else
            {
                ret += right - cur2 + 1;
                tmp[i++] = nums[cur1++];
            }
        }

        //排序
        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-left];
        return ret;
    }
};

运行结果:

image-20231203125139503

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

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

相关文章

jdk1.8 hashmap源码阅读

目录 hashmap 成员变量 hashmap支持null键吗&#xff1f;为什么&#xff1f; 当扩容的时候&#xff0c;所有元素都会重新计算hash值吗&#xff1f; 怎么减少扩容次数 为什么node数组的大小是2的n次&#xff1f; 1.8和1.7的区别 1.8为啥要用红黑树&#xff1f; 扩容机制…

右值引用和移动语句(C++11)

左值引用和右值引用 回顾引用 我们之前就了解到了左值引用&#xff0c;首先我们要了解引用在编译器底层其实就是指针。具体来说&#xff0c;当声明引用时&#xff0c;编译器会在底层生成一个指针来表示引用&#xff0c;但在代码编写和使用时&#xff0c;我们可以像使用变量类…

面试题:MySQL为什么选择B+树作为索引结构

文章目录 前言二、平衡二叉树(AVL)&#xff1a;旋转耗时三、红黑树&#xff1a;树太高四、B树&#xff1a;为磁盘而生五、B树六、感受B树的威力七、总结 前言 在MySQL中&#xff0c;无论是Innodb还是MyIsam&#xff0c;都使用了B树作索引结构(这里不考虑hash等其他索引)。本文…

一缕青丝寄相思

10年8月16日七夕节男孩向女孩表白,女孩不知道那天是七夕,也没有读懂男孩的爱,女孩在9月22日中秋,向男孩打开了心门,男孩却没有懂女孩的心思.13年后的一封问候邮件,一束女孩的长发和回不去的青春 洒满阳光的午后 转眼间看到你的笑脸 微笑着你对我说 遇上你认识我真好 你说得好莫…

数据结构与算法(Java) -单调队列单调栈题单

单调队列&#xff08;灵神笔记&#xff09; 239 滑动窗口最大值 239. 滑动窗口最大值 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗…

找不到DNS地址的解决方案

找不到DNS地址的解决方案 第一种解决方案&#xff1a;刷新DNS缓存第二种解决方案&#xff1a; 配置Internet协议版本4&#xff08;TCP/IPv4&#xff09;配置IP地址配置DNS地址 如何查看本机IPv4地址、子网掩码与默认网关 第一种解决方案&#xff1a;刷新DNS缓存 WINR输入cmd回…

对比ProtoBuf和JSON的序列化和反序列化能力

1.序列化能力对比验证 在这里让我们分别使用PB与JSON的序列化与反序列化能力&#xff0c;对值完全相同的一份结构化数据进行不同次数的性能测试。 为了可读性&#xff0c;下面这一份文本使用JSON格式展示了需要被进行测试的结构化数据内容: {"age" : 20,"name…

2023年第十二届数学建模国际赛小美赛A题太阳黑子预测求解分析

2023年第十二届数学建模国际赛小美赛 A题 太阳黑子预测 原题再现&#xff1a; 太阳黑子是太阳光球上的一种现象&#xff0c;表现为比周围区域暗的暂时斑点。它们是由抑制对流的磁通量浓度引起的表面温度降低区域。太阳黑子出现在活跃区域内&#xff0c;通常成对出现&#xff…

Android自定义View实现八大行星绕太阳转动效果

最近尝试使用Android自定义View实现了一个8大行星绕太阳转动的自定义View效果&#xff0c;效果静态图如下所示&#xff1a; 还没来得及对该效果进行比较通用的包装&#xff0c;仅仅实现效果&#xff0c;有兴趣的可以继续扩展、美化、包装一下。 核心代码就一个类PlanetsView。 …

js中setinterval怎么用?怎么才能让setinterval停下来?

setinterval()是定时调用的函数&#xff0c;可按照指定的周期&#xff08;以毫秒计&#xff09;来调用函数或计算表达式。 setinterval()的作用是在播放动画的时&#xff0c;每隔一定时间就调用函数&#xff0c;方法或对象。 setInterval() 方法会不停地调用函数&#xff0c;…

Stm32F401RCT6内部FLASH数据擦除读写方法

Stm32F401RCT6内部FLASH数据的分区和F103的已经不一样了&#xff0c;读写格式化的方法网上内容不多&#xff0c;自己摸索了一下&#xff0c;基本可以&#xff0c;还存在一个问题 读取&#xff1a; uint16_t f[5];uint8_t tx[10];f[0] *(volatile uint16_t*)0x08020000; //ST…

tar文件覆盖漏洞 CVE-2007-4559

文章目录 前言原理例题 [NSSRound#7 Team]新的博客方法一 手搓文件名方法二 python脚本 前言 做到[NSSRound#6 Team]check(Revenge)时发现是tar文件覆盖&#xff0c;但是对概念和执行过程理解不够深就光光记住脚本&#xff0c;所以在做本题[NSSRound#7 Team]新的博客时打算重新…

一个网站,四种创建制作电子期刊的方法

想象一下&#xff0c;你正在走进一家神奇的商店&#xff0c;里面陈列着各种精美的杂志和期刊。但是&#xff0c;这些杂志和期刊并不是印刷品&#xff0c;而是可以直接在网站上制作和发布的电子期刊。 但是像这样能在网上发的电子期刊该怎么制作呢&#xff1f;不知道如何制作的小…

cc-product-waterfall仿天猫、淘宝购物车店铺商品列表组件

cc-product-waterfall仿天猫、淘宝购物车店铺商品列表组件 引言 在电商应用中&#xff0c;购物车体验的优化对于提升用户满意度和转化率至关重要。在本文中&#xff0c;我们将深入探讨如何使用cc-product-waterfall组件&#xff0c;结合uni-number-box和xg-widget&#xff0c;…

『Nginx安全访问控制』利用Nginx实现账号密码认证登录的最佳实践

&#x1f4e3;读完这篇文章里你能收获到 如何创建用户账号和密码文件&#xff0c;并生成加密密码配置Nginx的认证模块&#xff0c;实现基于账号密码的登录验证 文章目录 一、创建账号密码文件1. 安装htpasswd工具1.1 CentOS1.2 Ubuntu 二、配置Nginx三、重启Nginx 在Web应用程…

Linux驱动开发学习笔记1《字符设备驱动开发》

目录 一、字符设备驱动简介 二、chrdevbase 字符设备驱动开发实验 1.创建驱动程序的目录 2.创建vscode工程 3.编写实验程序 4.编译驱动程序和测试APP代码 &#xff08;1&#xff09;加载驱动模块 &#xff08;2&#xff09;创建设备节点文件 &#xff08;3&#xff…

【开源】前后端分离的在线考试系统,支持多种部署方式

在线考试系统 https://download.csdn.net/download/mo3408/88593116 在线考试系统是一种利用网络技术&#xff0c;实现在线出题、答题、阅卷、成绩查询等一系列考试活动的系统。它不受地理位置限制&#xff0c;可以实现远程考试&#xff0c;大大提高了考试的效率和便利性。此…

HBASE命令行查看中文字符

问题记录 中文显示的是编码字符不方便查看value\xE5\xB8\xB8\xE5\xAE\x89\xE5\xAE\x891修改前中文显示&#xff1a; 解决方法 1、列族 : 列名 : toString ’2、列族 : 列名 : c(org.apache.hadoop.hbase.util.Bytes).toString ’ scan karry:student,{COLUMNS > [info:…

C-语言每日刷题

目录 [蓝桥杯 2015 省 A] 饮料换购 题目描述 输入格式 输出格式 输入输出样例 # [蓝桥杯 2023 省 A] 平方差 题目描述 输入格式 输出格式 输入输出样例 说明/提示 【样例说明】 [NOIP2001 普及组] 数的计算 题目描述 输入格式 输出格式 输入输出样例 说明/提示 样例 1 解释 数据…

SQL自学通之简介

目录 一、SQL 简史 二、数据库简史 1、Dr. Codds 对关系型数据库系统的十二条规则 2、设计数据库的结构 3、数据库的前景 4、对于什么是客户机/服务器型电脑系统 BernardH.Boar的定义如下&#xff1a; 5、交互式语言 6、易于实现 7、SQL 总览 三、流行的 SQL 开发工具…