进阶数据结构——离散化

目录

  • 一、离散化的核心思想与本质
  • 二、离散化的应用场景
  • 三、离散化的实现步骤
  • 四、离散化的复杂度分析
  • 五、离散化的优化技巧
  • 六、常见误区与调试技巧
  • 七、代码模版(c++)
  • 八、经典例题
    • 数列离散化
    • 寻找满足高度的最大山峦美丽值
  • 九、总结与学习建议

在这里插入图片描述

一、离散化的核心思想与本质

核心思想:离散化是一种将连续数据映射到有限离散值的技术,通常用于处理大规模数据或稀疏数据。
本质:通过将原始数据重新编号或映射,减少数据的规模和复杂度,同时保留数据的相对关系。

二、离散化的应用场景

区间查询与更新

在线段树或树状数组中,离散化可以将大范围的坐标映射到小范围的索引,节省空间和时间。

示例:LeetCode 315. 计算右侧小于当前元素的个数。

统计与计数:

在统计频次或计数问题中,离散化可以减少数据规模,提高效率。

示例:LeetCode 493. 翻转对。

图论与网络流:

在图论问题中,离散化可以将大范围的节点编号映射到小范围,简化问题。

示例:LeetCode 685. 冗余连接 II。

几何问题:

在几何问题中,离散化可以将连续的坐标映射到离散的网格点,简化计算。

示例:LeetCode 850. 矩形面积 II。

三、离散化的实现步骤

  1. 数据收集
    收集所有需要离散化的数据点(如坐标、值等)。

  2. 排序与去重
    对数据点进行排序,并去除重复值。

  3. 映射与编号
    将原始数据点映射到离散的索引(通常从 0 或 1 开始)。

  4. 应用离散化
    使用映射后的索引代替原始数据点进行计算或存储。

四、离散化的复杂度分析

时间复杂度
排序与去重:
O(nlogn),其中
n 是数据点的数量。

映射与编号:
O(n)。

空间复杂度
存储映射关系:
O(n)。

五、离散化的优化技巧

  1. 二分查找优化
    在映射过程中,使用二分查找快速确定数据点的离散索引。

  2. 动态离散化
    在动态数据流中,实时维护离散化映射。

  3. 多维度离散化
    在多维数据中,分别对每个维度进行离散化。

六、常见误区与调试技巧

  1. 误区一:离散化会丢失信息
    澄清:离散化仅改变数据的表示方式,不改变数据的相对关系。

  2. 误区二:离散化适用于所有问题
    澄清:离散化适用于数据范围大但数据点稀疏的问题,对于密集数据可能不适用。

  3. 调试方法
    打印映射关系:在离散化后输出映射关系,检查是否正确。

可视化数据分布:绘制原始数据和离散化后的数据分布,检查一致性。

七、代码模版(c++)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

template<class T>
class Dicretizer {
private:
	vector<T>m_data;
public:
	void addData(T v);
	void process();
	int getData(T v) const;
	int size()const;
};

template<class T>
void Dicretizer<T>::addData(T v) {
	m_data.push_back(v);
}

template<class T>
void Dicretizer<T>::process() {
	sort(m_data.begin(), m_data.end());
	int lastId = 0;
	for (int i = 1; i < m_data.size(); i++) {
		T t = m_data[i];
		if (t != m_data[lastId]) {
			m_data[++lastId] = t;
		}
	}
	while (lastId < m_data.size() - 1) {
		m_data.pop_back();
	}
}

template<class T>
int Dicretizer<T>::getData(T v) const {
	int l = -1, r = m_data.size();
	while (l + 1 < r) {
		int mid = (l + r) / 2;
		if (m_data[mid] >= v)r = mid;
		else l = mid;
	}
	if (m_data[r] != v || r == m_data.size())return -1;
	return r;
}

template<class T>
int Dicretizer<T>::size() const {
	return m_data.size();
}

int main() {

	return 0;
}

八、经典例题

数列离散化

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

template<class T>
class Dicretizer {
private:
	vector<T>m_data;
public:
	void addData(T v);
	void process();
	int get(T v) const;
	int size() const;
};


template<class T>
void Dicretizer<T>::addData(T v) {
	m_data.push_back(v);
}

template<class T>
void Dicretizer<T>::process() {
	sort(m_data.begin(), m_data.end());
	int lastId = 0;
	for (int i = 1; i < m_data.size(); i++) {
		T x = m_data[i];
		if (x != m_data[lastId]) {
			m_data[++lastId] = x;
		}
	}
	while (lastId < m_data.size() - 1) {
		m_data.pop_back();
	}
}

template<class T>
int Dicretizer<T>::get(T v) const {
	int l = -1, r = m_data.size();
	while (l + 1 < r) {
		int mid = (l + r) / 2;
		if (m_data[mid] >= v)r = mid;
		else l = mid;
	}
	if (r == m_data.size() || m_data[r] != v)return -1;
	return r;
}

template<class T>
int Dicretizer<T>::size() const {
	return m_data.size();
}

int a[100001];

int main() {
	int n;
	cin >> n;
	while (n--) {
		int s;
		cin >> s;
		Dicretizer<int> d;
		for (int i = 0; i < s; i++) {
			int x;
			cin >> x;
			a[i] = x;
			d.addData(x);
		}
		d.process();
		for (int i = 0; i < s; i++) {
			cout << d.get(a[i]) + 1 << ' ';		//因为数组下标是从0开始,所以加一
		}
		cout << endl;
	}
	return 0;
}


寻找满足高度的最大山峦美丽值

这道题太恶心了,实在不懂也没关系。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

template<class T>
class Dicretizer {
private:
	vector<T>m_data;
public:
	void addData(T v);
	void process();
	int getData(T v) const;
	int size()const;
};

template<class T>
void Dicretizer<T>::addData(T v) {
	m_data.push_back(v);
}

template<class T>
void Dicretizer<T>::process() {
	sort(m_data.begin(), m_data.end());
	int lastId = 0;
	for (int i = 1; i < m_data.size(); i++) {
		T t = m_data[i];
		if (t != m_data[lastId]) {
			m_data[++lastId] = t;
		}
	}
	while (lastId < m_data.size() - 1) {
		m_data.pop_back();
	}
}

template<class T>
int Dicretizer<T>::getData(T v) const {
	int l = -1, r = m_data.size();
	while (l + 1 < r) {
		int mid = (l + r) / 2;
		if (m_data[mid] >= v)r = mid;
		else l = mid;
	}
	if (m_data[r] != v || r == m_data.size())return -1;
	return r;
}

template<class T>
int Dicretizer<T>::size() const {
	return m_data.size();
}

#define maxn 200001

struct HB {
	int h, b;
}hb[maxn];
int k[maxn], maxv[maxn];		//k作为询问数组,maxv代表限高的最大美丽值

bool cmp(const HB& a, const HB& b) {
	return a.h < b.h;
}

int main() {
	Dicretizer<int>d;
	int n, q;
	cin >> n >> q;
	for (int i = 0; i < n; i++) {
		cin >> hb[i].h;
		d.addData(hb[i].h);
	}
	for (int i = 0; i < n; i++) {
		cin >> hb[i].b;
	}
	for (int i = 0; i < q; i++) {
		cin >> k[i];
		d.addData(k[i]);
	}
	d.process();
	for (int i = 0; i < n; i++) {
		hb[i].h = d.getData(hb[i].h);
	}
	for (int i = 0; i < q; i++) {
		k[i] = d.getData(k[i]);
	}
	sort(hb, hb + n, cmp);
	maxv[d.size()] = -1;
	int j = n - 1;
	for (int i = d.size() - 1; i >= 0; i--) {
		maxv[i] = maxv[i + 1];
		while(j >= 0 && hb[j].h == i) {
			if(hb[j].b > maxv[i]) {
				maxv[i] = hb[j].b;
			}
			j--;
		}
	}
	for (int i = 0; i < q; i++) {
		int x = k[i];
		cout << maxv[x] << endl;
	}
	return 0;
}

九、总结与学习建议

  1. 核心总结
    离散化是一种将连续数据映射到离散值的技术,适用于处理大规模或稀疏数据。

通过排序、去重和映射,可以高效实现离散化。

  1. 学习建议
    分类刷题:按问题类型集中练习(如区间查询、统计计数、几何问题)。

理解算法原理:掌握离散化的实现步骤和优化技巧。

手写模拟过程:在纸上模拟离散化的过程,加深直观理解。

在这里插入图片描述
希望大家可以一键三连,后续我们一起学习,谢谢大家!!!
在这里插入图片描述

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

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

相关文章

VNC远程控制Mac

前言 macOS系统自带有VNC远程桌面&#xff0c;我们可以在控制端上安装配置VNC客户端&#xff0c;以此来实现远程控制macOS。但通常需要在不同网络下进行远程控制&#xff0c;为此&#xff0c;我们可以在macOS被控端上使用cpolar做内网穿透&#xff0c;映射VNC默认端口5…

[0689].第04节:Kafka与第三方的集成 – Kafka集成SpringBoot

Kafka笔记大纲 SpringBoot 是一个在 JavaEE 开发中非常常用的组件。可以用于 Kafka 的生产者&#xff0c;也可以用于 SpringBoot 的消费者 一、SpringBoot 环境准备 1.1.创建一个 Spring Initializr 1.2.引入场景启动器&#xff1a; <?xml version"1.0" encod…

「软件设计模式」装饰者模式(Decorator)

深入解析装饰者模式&#xff1a;动态扩展功能的艺术&#xff08;C实现&#xff09; 一、模式思想与应用场景 1.1 模式定义 装饰者模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过将对象放入包含行为的特殊封装对象中&#xff0c;动态地…

简单几个步骤完成 Oracle 到金仓数据库(KingbaseES)的迁移目标

作为国产数据库的领军选手&#xff0c;金仓数据库&#xff08;KingbaseES&#xff09;凭借其成熟的技术架构和广泛的市场覆盖&#xff0c;在国内众多领域中扮演着至关重要的角色。无论是国家电网、金融行业&#xff0c;还是铁路、医疗等关键领域&#xff0c;金仓数据库都以其卓…

【Jenkins流水线搭建】

Jenkins流水线搭建 01、SpringBoot项目 - Jenkins基于Jar持续集成搭建文档基于手动方式发布项目基于dockerfile基于jenkins + dockerfile + jenkinsfile +pieline基于jenkins + jar方式的发布01、环境说明01、准备项目02、准备服务器03、安装git04、安装jdk1.805、安装maven依赖…

简单记录一下自己对springboot过程的理解

仅为个人简单理解&#xff0c;欢迎大家来一起讨论。 执行启动类main函数&#xff1b;读取依赖和配置文件&#xff1b;创建spring容器&#xff0c;并自动注入Bean&#xff1b;启动Tomcat。

使用 GPT-SoVITS 克隆声音,很详细

使用 GPT-SoVITS 克隆声音&#xff0c;很详细 一、前言二、下载三、启动四、克隆声音1、准备克隆音频2、分离人声伴奏3、音频分割4、语音降噪5、ASR工具6、语音文本校对标注工具7、训练模型8、微调训练9、推理 一、前言 最近对文本转语言很感兴趣&#xff0c;但对直接在网站上…

金融风控项目-业务基础

文章目录 一. 案例背景介绍二. 代码实现1. 加载数据2. 数据处理3. 查询 三. 业务解读 一. 案例背景介绍 通过对业务数据分析了解信贷业务状况 数据集说明 从开源数据改造而来&#xff0c;基本反映真实业务数据销售&#xff0c;客服可以忽略账单周期&#xff0c;放款日期账单金…

Django 创建表时 “__str__ ”方法的使用

在 Django 模型中&#xff0c;__str__ 方法是一个 Python 特殊方法&#xff08;也称为“魔术方法”&#xff09;&#xff0c;用于定义对象的字符串表示形式。它的作用是控制当对象被转换为字符串时&#xff0c;应该返回什么样的内容。 示例&#xff1a; 我在初学ModelForm时尝…

Spring Boot中如何自定义Starter

文章目录 Spring Boot中如何自定义Starter概念和作用1. 概念介绍2. 作用和优势2.1 简化依赖管理2.2 提供开箱即用的自动配置2.3 标准化和模块化开发2.4 提高开发效率2.5 提供灵活的配置覆盖3. 应用场景创建核心依赖1. 确定核心依赖的作用2. 创建 starter-core 模块2.1 依赖管理…

Python 面向对象的三大特征

前言&#xff1a;本篇讲解面向对象的三大特征&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff0c;还有比较细致的&#xff08;类属性类方法&#xff0c;静态方法&#xff09;&#xff0c;分步骤讲解&#xff0c;比较适合理清楚三大特征的思路 面向对象的…

Windows 11 安装 Docker

1.以管理员身份打开 Windows PowerShell 2.执行下面三行命令来启动WSL和虚拟机平台 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestartdism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norest…

CRMEB PHP多门店版v3.1.1源码全开源+PC端+Uniapp前端+搭建教程

一.介绍 CRMEB多店版是一款为品牌连锁门店打造的私域电商解决方案&#xff0c;以三大运营模式为核心&#xff0c;助力品牌连锁门店轻松构建全渠道、一体化的私域电商生态&#xff0c;促进“线上电商”与“线下门店”销售运营融合&#xff0c;加速品牌数字化转型&#xff0c;为…

Notepad++ 中删除所有以 “pdf“ 结尾的行

Notepad 中删除所有以 “pdf” 结尾的行 操作步骤 1.打开文件&#xff1a; 在 Notepad 中打开你需要处理的文本文件。 2.打开查找和替换对话框&#xff1a; 按快捷键 Ctrl F&#xff0c;打开“查找和替换”对话框。 3.启用正则表达式模式&#xff1a; 在对话框的底部&#xf…

基于SSM+uniapp的鲜花销售小程序+LW示例参考

1.项目介绍 系统角色&#xff1a;管理员、商户功能模块&#xff1a;用户管理、商户管理、鲜花分类管理、鲜花管理、订单管理、收藏管理、购物车、充值、下单等技术选型&#xff1a;SSM&#xff0c;Vue&#xff08;后端管理web&#xff09;&#xff0c;uniapp等测试环境&#x…

项目版本号生成

需求 项目想要生成一个更新版本号&#xff0c;格式为v2.0.20250101。 其中v2.0为版本号&#xff0c;更新时进行配置&#xff1b;20250101为更新日期&#xff0c;版本更新时自动生成。 实现思路 创建一个配置文件version.properties&#xff0c;在其中配置版本号&#xff1b…

Unity UI个人总结

个人总结&#xff0c;太简单的直接跳过。 一、缩放模式 1.固定像素大小 就是设置一个100x100的方框&#xff0c;在1920x1080像素下在屏幕中长度占比1/19&#xff0c;在3840x2160&#xff0c;方框在屏幕中长度占比1/38。也就是像素长款不变&#xff0c;在屏幕中占比发生变化 2.…

ArcGIS基础知识之ArcMap基础设置——ArcMap选项:常规选项卡设置及作用

作为一名 GIS 从业者,ArcMap 是我们日常工作中不可或缺的工具。对于初学者来说,掌握 ArcMap 的基础设置是迈向 GIS 分析与制图的第一步。今天,就让我们一起深入了解 ArcMap 选项中常规选项卡的各个设置,帮助大家更好地使用这款强大的软件。 在 ArcMap 中,常规选项卡是用户…

jenkins war Windows安装

Windows安装Jenkins 需求1.下载jenkins.war2.编写快速运行脚本3.启动Jenkins4.Jenkins使用 需求 1.支持在Windows下便捷运行Jenkins&#xff1b; 2.支持自定义启动参数&#xff1b; 3.有快速运行的脚步样板。 1.下载jenkins.war Jenkins下载地址&#xff1a;https://get.j…

知识管理成功:关键指标和策略,研究信息的投资回报率

信息过载会影响生产力。没有人工智能的帮助&#xff0c;信息过载会影响生产力。大量的可用信息&#xff0c;知识工作者不仅仅是超负荷工作&#xff1b;他们感到不知所措&#xff0c;他们倾向于浪费时间&#xff08;和脑细胞&#xff09;来应付他们被大量的数据抛向他们&#xf…