分治-归并排序

2023-12-05

在这里插入图片描述

????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 <= 10 5
  • -10 4 <= nums[i] <= 10 4

⛅2. 算法原理

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

解法一:暴力枚举

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

解法二:分治

如图:

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 < j nums[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(N 2 ),应该会超时

解法二:分治

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

还是两种策略:

  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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分治-归并排序 的相关文章

随机推荐

  • 头歌—密码学基础

    第1关 哈希函数 题目 任务描述 本关任务 利用哈希算法统计每个字符串出现的个数 相关知识 为了完成本关任务 你需要掌握 1 密码学哈希函数的概念及特性 2 安全哈希算法 密码学哈希函数的概念及特性 我们需要理解的第一个密码学的基础知识是密
  • EasyRecovery易恢复2024最新免费版电脑数据恢复软件功能介绍

    EasyRecovery从 易恢复2024 支持恢复不同存储介质数据 在Windows中恢复受损和删除文件 以及能检索数据格式化或损坏卷 甚至还可以从初始化磁盘 同时 你只需要最简单的操作就可以恢复数据文件 如 硬盘 光盘 U盘 移动硬盘
  • 用Python手把手教你实现一个爬虫(含前端界面)

    目录 前言 爬虫基本原理 使用Python的requests库发送HTTP请求 使用BeautifulSoup库解析HTML页面 使用PyQt5构建前端界面 实现一个完整的爬虫程序 结语 前言 随着互联网的飞速发展 再加上科技圈的技术翻天覆
  • FL Studio2024水果编曲软件21.2.0中文版本下载更新

    FL Studio2024是功能强大的音乐制作解决方案 使用旨在为用户提供一个友好完整的音乐创建环境 让您能够轻松创建 管理 编辑 混合具有专业品质的音乐 一切的一切都集中在一个软件中 只要您想 只要您需要 它总能满足您的音乐需求 工具方面
  • 拼多多财报解读:连接高质量供给与全球消费者,多多跨境动力澎湃

    题解 牛牛的排序 include
  • 链表【1】

    文章目录 2 两数相加 1 题目 2 算法原理 3 代码实现 445 两数相加 II
  • FL Studio21.2.0中文完整版Crack

    Fl Studio21是最好的音乐制作软件 但它的成本超过300美元 一个年轻的新音乐创作者怎么能从上到下 地球上没有比 FL Studio 21 更完整的音乐制作软件了 14 年来 它一直是行业领导者 并且随着随后的每一次更新 在此之前已
  • 最后一次改简历了,麻烦牛客的大佬们最后指导我一下吧

    题解 操作符混合运用 SELECT device id gender age university gpafrom user profilewhere gpa in 3 5 3 8 京东实习 全程1H 记录一下1 自我介绍2 介绍项目亮点3
  • 牛客周赛 Round 22 解题报告 | 珂学家 | 思维构造 + 最小生成树

    题解 提取不重复的整数 import java util HashSet import java util Scanner 注意类名必须为 Main 不要有任何 package 题解 计算三角形的周长和面积 include
  • 链表【2】

    文章目录 24 两两交换链表中的节点 题目 算法原理 代码实现 143 重排链表
  • 谈谈 .NET8 平台中对 LiteDB 的 CRUD 操作

    哪个啥 纯 C 编写的 LiteDB 你还不会操作 LiteDB 简介 LiteDB 安装 1 同步版 LiteDB 2 异步版 LiteDB Async LiteDB Studio LiteDB CRUD 操作举例 1 net cli 命
  • 【LeetCode:1423. 可获得的最大点数 | 滑动窗口】

    算法题 算法刷题专栏 面试必备算法 面试高频算法 越难的东西 越要努力坚持 因为它具有很高的价值 算法就是这样 作者简介 硕风和炜 CSDN Java领域新星创作者 保研 国家奖学金 高中学习JAVA 大学完善JAVA开发技术栈 面试刷题
  • LeetCode:1038. 从二叉搜索树到更大和树(反向中序遍历 C++、Java)

    目录 1038 从二叉搜索树到更大和树 题目描述 实现代码与解析 dfs 原理思路 1038 从二叉搜索树到更大和树 题目描述 给定一个二叉搜索树 root BST 请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和 提醒一
  • SSM 线上知识竞赛系统-计算机毕设 附源码 27170

    SSM线上知识竞赛系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化 电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用 信息时代的到来已成为不可阻挡的时尚潮流 人类发展的历史正进入一个新时代 在现实运用中 应
  • FL Studio2024中文语言版水果编曲软件

    FL Studio21 2这款软件在国内被广泛使用 因此又被称为 水果 它提供音符编辑器 可以针对作曲者的要求编辑出不同音律的节奏 例如鼓 镲 锣 钢琴 笛 大提琴 筝 扬琴等等任何乐器的节奏律动 此外 它还提供了方便快捷的音源输入 对于在
  • “丝路电商”与泛欧在线公共采购平台Peppol

    近期上海商务委员会公布 关于在上海市创建 丝路电商 合作先行区的方案 以下简称方案 方案中提出 全面贯彻落实党的二十大精神 立足新发展阶段 完整 准确 全面贯彻新发展理念 加快构建新发展格局 统筹发展和安全 发挥上海在改革开放中的突破攻坚作
  • Springboot养老院信息管理系统的开发-计算机毕设 附源码 27500

    Springboot养老院信息管理系统的开发 摘 要 随着互联网趋势的到来 各行各业都在考虑利用互联网将自己推广出去 最好方式就是建立自己的互联网系统 并对其进行维护和管理 在现实运用中 应用软件的工作规则和开发步骤 采用Springboo
  • 分治—快速选择算法

    文章目录 215 数组中的第K个最大元素 1 题目 2 算法原理 3 代码实现 LCR 159 库存管理 III
  • 分治-归并算法——LCR 170. 交易逆序对的总数

    文章目录 0 归并排序 1 题目 2 算法原理 3 代码实现 0 归并排序 归并排序是典型的分治 将数组分成若干个子数组 数组两两比较 不是很清楚的 可以查看此篇文章 数据结构 七大排序 这里以力扣 9
  • 分治-归并排序

    文章目录 315 计算右侧小于当前元素的个数 1 题目 2 算法原理 3 代码实现 493 翻转对