算法笔记:离散化的两种实现方式

在一些场景或题目中,常常会遇到数据跨度较大的一堆数据。如果需要用连续空间存储,则会有大量空闲的空间,并且遍历的时间复杂取决于最大和最小值的间距。

如果不关系数据的具体大小,只关心数据的相对顺序,那么就可以用到本文重点离散化。

在这里插入图片描述
那么,什么是离散化?

离散化是指,将无限的数据,映射到有限的空间中并保留原来的全 / 偏序关系。
举个例子:

在这里插入图片描述

在这里插入图片描述
实现原理

以下以一维数组给出示例,将数据离散化到[0, n-1]的范围

例:
在这里插入图片描述

思路一:下标映射

如果将下标也一同排序,数据将是怎么的形式呢?
在这里插入图片描述
将下标和元素绑定后,有一个好处,对应每个元素能 O(1) 的找出该元素在原始数组中的位置。

因此,我们只需要顺序遍历排序后的元素,顺序的将原数组的值改为[0, n-1]的映射即可。

具体的我们可以如下操作:

排序后的第 0 号元素 —> 获取原数组 index 1 —> 将原数组的 1 号元素修改为 0 。

排序后的第 1 号元素 —> 获取原数组 index 4 —> 将原数组的 4 号元素修改为 1 。

排序后的第 2 号元素 —> 获取原数组 index 2 —> 将原数组的 2 号元素修改为 2 。

排序后的第 3 号元素 —> 获取原数组 index 3 —> 将原数组的 3 号元素修改为 3 。

排序后的第 4 号元素 —> 获取原数组 index 0 —> 将原数组的 0 号元素修改为 4 。

思路二:二分

其实这里的二分法回归本源也是基于下标映射的原理,只是实现是借助二分的形式。

在排序好的数组中对目标数值进行二分搜索,在 O(logn) 的时间复杂度内找到该数值是整体数据中的第几个。

具体的我们可以如下操作:
数值 10 —> 二分搜索 10 —> 有序序列中第 4 位置。

数值 3 —> 二分搜索 3 —> 有序序列中第 0 位置。

数值 8 —> 二分搜索 8 —> 有序序列中第 9 位置。

数值 9 —> 二分搜索 9 —> 有序序列中第 3 位置。

数值 4 —> 二分搜索 4 —> 有序序列中第 1 位置。

复杂度

时间复杂度:O(logn),主要体现在排序中,其余操作 <= O(logn) 。

空间复杂度:O(n),主要体现在用于排序的辅助数组中,不考虑 sort 中使用的空间。

在这里插入图片描述
代码

对下方代码的注释:

  1. 以 C++ 描述
  2. 以整形数据 int 描述
  3. 默认数据无重复值
  4. 接口名见下
/**
 * @param odata 原始数据
 * @param start 起始数值 (一般为0/1)
 * @return std::vector<int> 经过离散化后的data
 */
vector<int> discrete(const vector<int>& odata, int start = 0) ;

排序 + 下标映射
sort 排序

vector<int> discrete(const vector<int>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值