排序算法: 数据的离散化(排序+去重 C++例题实现)

news2024/9/20 18:34:29

文章目录

  • 数据的离散化
    • 例题:电影
    • 完整代码

数据的离散化

离散化是指将一个无穷大的集合中的若干个元素映射到一个有限的集合中,以便于对那个无穷大的集合进行操作。

在很多情况下:对于一个规定在Z范围内的整数范围,他有可能包含非常多的重复的元素,真正不同的元素仅有M个,因此我们考虑把这Z个元素进行映射到只包含M个元素的集合中,即与 【1-M】个整数建立映射关系。因此如果一个算法的时间空间复杂度与Z有关,则会降低到与M有关,对于某些重复元素非常多的集合,将会大大提高算法的复杂度


那么显而易见:离散化的首要目的便是给包含Z个元素的集合去重,使得它不包含任意的重复元素,每个元素只出现一次,然后映射到另一个无任何重复元素的集合中,这个集合只包含M个元素。

  1. 我们把a集合中的某一个元素a[i]映射到b[j]中,b[j]中不含任意重复的元素,相当于是排序+去重后得a集合(可以使用STL的unique实现这个功能)
  2. 我们想要得知 j 这个序号表示的是哪一个a集合中的元素,即表示哪一个a[i],只需要返回b[j]即可
  3. 我们想要得知 a[i]这个元素,在b集合中被哪一个序号i所表示,我们就可以使用二分查找来找到它的位置。
int a[11] = { 0,1,1,2,3,4,5,6,9,2,7 };	//注意下标从1开始,a[0]是凑数的
int b[11], m = 0;
void discrete()
{
	//排序,去重,实现离散化
	sort(a+1,a+1+10);
	for (int i=1;i<=n;i++)
	{	
		if (i==1 || a[i]!=a[i-1])
		{
			b[++m]=a[i];
		}
	}
}
int find(int x)
{
	return lower_bound(b+1,b+1+m,x)-b;
}

举例:

int main()
{
	discrete();
	cout << b[8] << endl;		//查询i=8(1<=i<=m)代替的是哪一个数值:直接返回b[i]
	cout << query(5) << endl;   //查询a[j]的值被哪个i替代,只需要二分查找a[j]即可

	return 0;
}

在这里插入图片描述


例题:电影

AcWing 103 电影

这是一道利用了离散化数据的例题。

可以看到此题中关于语言这一个量的限制达到了10^9 ,并且对于这个语言,我们貌似还必须要用一个数组存储起来,否则就无法操作,因此我们的数组就会存储一个非常大的集合,并且我们的数组还不一定能装下,因此我们考虑使用离散化

做法:

  1. 首先收集所有的语言:使用ori数组。
  2. 然后对于ori数组进行离散化处理,保存离散化数据到uni中。
  3. 根据离散化的数据集合得到每一位科学家懂得的语言编号,保存在ans数组中。
  4. 遍历所有电影,对于每一个电影,分别求出能够使科学家达到很开心的科学家的人数,其次求出达到比较开心的人数,然后对于这两个数据和以前的值取一个最大的值,记录电影编号。

首先收集所有语言:全部存在ori数组里,数组的下标使用tot记录

 cin >> n;  //n:n位科学家  
    for (int i = 1; i <= n; i++)
    {
        //科学家懂得的语言编号
        cin >> p[i];
        ori[++tot] = p[i];    //原始数据全部存在ori中
    }
    cin >> m; //m:m个电影
    for (int i = 1; i <= m; i++)
    {
        //每一部电影的语音语言
        cin >> y[i];
        ori[++tot] = y[i];
    }
    for (int i = 1; i <= m; i++)
    {
        //每一部电影的字幕语言
        cin >> z[i];
        ori[++tot] = z[i];
    }

然后进行离散化数据!!!!!!!!!!

把离散化数据存放在uni数组中

//排序
sort(ori + 1, ori + 1 + tot);
 //离散化数据
 for (int i = 1; i <= tot; i++)
 {
     if (i == 1 || ori[i] != ori[i - 1])
     {
         uni[++k] = ori[i];
     }
 }

注意:离散化的数据集合uni中只包含了所有的语言编号,并不包含任何其他数据,如人数等等,统计各个人数是在下一步进行的


统计懂得每种语言的科学家分别有多少人???

使用find进行查询:给出p[i]表示的是未离散化的大集合,要找到这个p[i]在离散化后被哪个编号i所映射,使用find函数。 得到的是一个映射标号i,然后ans[i]表示的是懂得第i种语言的人数。

for (int i = 1; i <= n; i++)
    {
        //查询懂得某种语言的人数有多少
        ans[find(p[i])]++;
    }

统计电影的语音和字幕的人数

同理:

  • ans[find(y[i])]:表示懂得第i部电影的语音的人数,因为在上一步我们已经预处理了懂得每种语言的人数,所有说把一个语言编号i传递给ans,得到的就是懂得 i语言的人数。
  • ans[find(x[i])]:懂得第i部电影的字幕的人数。

统计完成后,如果这一部电影的resy(懂得语音的人数)比上一部电影的resy多(注意:上一部电影的语音用res1保存,上一部的字幕用res2保存),那么更新电影编号;
如果相等,那么再比较字幕。。。

for (int i = 1; i <= m; i++)
{
    resy = ans[find(y[i])];//懂得语音的人数
    resz = ans[find(z[i])];//懂得字幕的人数
    if (resy > res1 || (resy == res1 && resz > res2))
    {
        res = i;  //记录电影编号
        res1 = resy;//记录这部电影的懂得语音的人数
        res2 = resz;//记录这部电影的懂得字幕的人数
    }
}

最后答案有可能会出现 没有一个人懂得某部电影的语音和字幕,则随便输出一个。

完整代码

!!!!!!!!!! 注意理解这些变量的名字,不要弄混了!!!!!!!!!!!

#include <bits/stdc++.h>
using namespace std;

/*
请你帮忙选择一部电影,可以让观影很开心的人最多。
如果有多部电影满足条件,则在这些电影中挑选观影比较开心的人最多的那一部。
*/
const int N = 200005;
int n, m, resy, resz, res, res1, res2, k = 0, tot = 0;
int p[N], y[N], z[N], ans[3 * N];
int ori[N * 3], uni[3 * N]; //ori存放原始数据,uni存放离散数据  多给点空间
int find(int x)
{
    //根据a[j]查询替代此a[j]值的序号j
    return lower_bound(uni + 1, uni + 1 + k, x) - uni;
}
int main()
{
    cin >> n;  //n:n位科学家  
    for (int i = 1; i <= n; i++)
    {
        //科学家懂得的语言编号
        cin >> p[i];
        ori[++tot] = p[i];    //原始数据全部存在ori中
    }
    cin >> m; //m:m个电影
    for (int i = 1; i <= m; i++)
    {
        //每一部电影的语音语言
        cin >> y[i];
        ori[++tot] = y[i];
    }
    for (int i = 1; i <= m; i++)
    {
        //每一部电影的字幕语言
        cin >> z[i];
        ori[++tot] = z[i];
    }
    //排序
    sort(ori + 1, ori + 1 + tot);
    //离散化数据
    for (int i = 1; i <= tot; i++)
    {
        if (i == 1 || ori[i] != ori[i - 1])
        {
            uni[++k] = ori[i];
        }
    }
    for (int i = 1; i <= n; i++)
    {
        //查询懂得某种语言的人数有多少
        ans[find(p[i])]++;
    }
    for (int i = 1; i <= m; i++)
    {
        resy = ans[find(y[i])];//懂得语音的人数
        resz = ans[find(z[i])];//懂得字幕的人数
        if (resy > res1 || (resy == res1 && resz > res2))
        {
            res = i;  //记录电影编号
            res1 = resy;//记录这部电影的懂得语音的人数
            res2 = resz;//记录这部电影的懂得字幕的人数
        }
    }
    if (res == 0)
    {
        cout << 1;
    }
    else
    {
        cout << res;
    }
    return 0;
}

参考:
《算法竞赛进阶指南》
AcWing 103 题解

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

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

相关文章

maven创建自定义web工程模板

一&#xff0c;先搭建好一个项目模板。 注意每个文件夹下都放一个文件占位&#xff0c;否则创建模板时会认为是空目录不进行创建。 注意项目文件夹名字 和 pom.xml 中<artifactId 和 <name 的名字都使用相同的名字&#xff0c;写一个好记的名字&#xff0c;因为后面生…

QT UI布局设置整理-边框设置

一、设置边距的方法 1、设置容器内部的内容控件的边距 //设置容器leftBar&#xff08;QWidget&#xff09;内部marginui->leftBar->setContentsMargins(10,10,0,0); 2、 设置内部控件之间的间距 //editWidget是一个QWidget ui->editWidget->layout()->setSpac…

【云原生kubernetes】k8s中控制器使用详解

一、什么是控制器 控制器是管理pod的中间层&#xff0c;只需要告诉Pod控制器&#xff0c;想要创建多少个什么样的Pod&#xff0c;它会创建出满足条件的Pod &#xff1b;控制器相当于一个状态机&#xff0c;用来控制Pod的具体状态和行为 &#xff1b;controller会自动创建相应的…

【数据库概论】3.2 SQL的查询、更新和删除语句

一、 数据查询 SQL提供SELECT语句用于查询&#xff0c;一般格式为&#xff1a; 根据WHERE子句条件表达式从FROM子句指定的基本表、视图中找出满足条件的元组 GROUP BY语句则用作将结果按照<列名1>的值进行分组&#xff0c;该属性列值相等的元组为一个组&#xff1b;ORD…

Essential C++第五章习题

目录 5.1 5.2 5.3 5.4 5.1 C代码&#xff1a; //Stack.h#include<vector> #include<string> #include<iostream> using namespace std;#pragma once#ifndef _STACK_H_ #define _STACK_H_typedef string elemType;class Stack { public://基类的析构函数…

【JavaSE专栏5】Java 基本数据类型和取值范围

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;Java全栈软件工程师一枚&#xff0c;来自浙江宁波&#xff0c;负责开发管理公司OA项目&#xff0c;专注软件前后端开发&#xff08;Vue、SpringBoot和微信小程序&#xff09;、系统定制、远程技术指导。CSDN学院、蓝桥云…

Mine Goose Duck 0.2版本发布

本次我增加了模组的1.16.5和1.18.2的适用版本&#xff0c;新增了一些职业和装扮 1.新职业 1.冒险家 你不会死于摔伤、溺水、火烧、冰冻。 2.工程师 你可以修改888范围内红石设备的状态。 3.模仿者 怪物认为你是他们的一员。 4.加拿大鹅 你会自动报警并召唤警车。 5.…

深度卷积对抗神经网络 基础 第三部分 (WGAN-GP)

深度卷积对抗神经网络 基础 第三部分 (WGAN-GP&#xff09; Wasserstein GAN with Gradient Penalty (WGAN-GP) 我们在训练对抗神经网络的时候总是出现各种各样的问题。比如说模式奔溃 (mode collapse)和 梯度消失&#xff08;vanishing gradient&#xff09;的问题。 比如说…

在linux下安装docker

文章目录 目录 文章目录 前言 一、docker 二、使用步骤 1.环境准备 2.安装 三、配置阿里云镜像加速 四、卸载 总结 前言 一、docker 镜像&#xff08;image&#xff09;&#xff1a; docker镜像就好比是一个模板&#xff0c;可以通过这个模板来创建容器服务&#xff0c;tomc…

【攻坚克难】详解k8s持久化存储数据pv、pvc存储问题

问题 如图:pod中的容器,创建一个包含文件的目录,重启pod或系统重启后,此目录及其文件都会丢失,如何保证其不会丢失? 图 1 创建包含文件的目录 方法 分析:用pv、pvc为k8s持久化存储数据是最好的选择,可解决上述问题。流程:pv → pvc → pod把创建的目录挂载到pvc上步…

路由 OSPF 优化(FA地址、路由汇总、路由过滤、区域认证、接口认证)

1.2.0 路由 OSPF 优化&#xff08;FA地址、路由汇总、路由过滤、区域认证、接口认证&#xff09; 一、FA地址 该文章介绍的FA地址说辞简单易懂&#xff1a;路由协议系列之六&#xff1a;OSPF FA地址 产生条件 ASBR在其连接外部网络的接口&#xff08;外部路由的出接口&#xf…

CS61A 2022 fall HW 01: Functions, Control

CS61A 2022 fall HW 01: Functions, Control 文章目录CS61A 2022 fall HW 01: Functions, ControlQ1: A Plus Abs BQ2: Two of ThreeQ3: Largest FactorQ4: HailstoneHW01对应的是Textbook的1.1和1.2 Q1: A Plus Abs B 题目&#xff1a; Fill in the blanks in the following f…

Java | 解决并发修改异常问题【CurrentModificationException】

今日碰到Java中的一个异常&#xff0c;名为CurrentModificationException&#xff0c;从属于RunTimeException运行时异常&#xff0c;故作此记录 异常解析 首先来说明一下什么是【并发修改异常】❓ 因为迭代器依赖集合而存在&#xff0c;因为当你在操作集合中元素的时候&#…

springboot中restful风格请求的使用

springboot中restful风格请求的使用restful风格springboot中的使用1.创建html表单页面2.在yml配置文件中开启rest表单支持3.编写controller层及对应映射处理4.启动服务&#xff0c;逐个访问restful风格 Rest风格支持&#xff08;使用HTTP请求方式动词来表示对资源的操作&#…

【手写 Vue2.x 源码】第四十二篇 - 组件部分 - 组件挂载流程简述

一&#xff0c;前言 上篇&#xff0c;组件部分-生成组件的真实节点&#xff1b; 本篇&#xff0c;组件部分-组件挂载流程分析&#xff1b; 二&#xff0c;组件挂载流程分析 1&#xff0c;示例 全局组件&#xff1a;my-button&#xff0c;name&#xff1a;‘全局组件’&…

什么是软件架构中的ASRs(架构需求文档)?

作者&#xff1a;非妃是公主 专栏&#xff1a;《软件工程》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 专栏地址 软件工程专栏地址 专栏系列文章 软件工程复习01&#xff1a;软件工程概述 软件工程复习02&#xf…

十大经典排序算法(动态演示+代码)-快速排序与希尔排序

快速排序 1.什么是快速排序 我们知道排序有很多种&#xff0c;常见的如希尔排序&#xff0c;插入排序&#xff0c;选择排序&#xff0c;堆排序等等&#xff0c;而快速排序也是排序家族中的一员。因为其在大多数情况下有着优秀的综合性能&#xff0c;快速排序的快速也算是实至…

结构型模式-享元模式

1.概述 运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销&#xff0c;从而提高系统资源的利用率。 2.结构 享元&#xff08;Flyweight &#xff09;模式中存在以下两种状态&#xff1a; 内…

信息论复习—信源编码的基本方法

目录 信源编码的目的&#xff1a;提高传输效率 离散信源&#xff1a; 离散信源的分类&#xff1a; 离散无记忆信源 (DMS: Discrete Memoryless Source&#xff09;&#xff1a; 离散无记忆信源的特点&#xff1a; 离散无记忆信源编码与译码&#xff1a; 等长编码的编码速…

Day869.索引(下) -MySQL实战

索引&#xff08;下&#xff09; Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于索引&#xff08;下&#xff09;的内容。 先来看一下这个问题&#xff1a; 下面这个表 T 中&#xff0c;如果执行 select * from T where k between 3 and 5&#xff0c;需要执行几次…