离散化
一、定义
离散化即为当只需关心数据的大小关系时而数据的范围又过大时,则可使用排名代替原数据进行处理的一种预处理;
离散化本质上是一种哈希,它在保持序列大小关系的前提下把其映射成正整数;
当原数据很大或含有负数,小数时,难以表示为数组下标,一些算法和数据结构无法运作,这时可以考虑将其散化;
离散化可以用 STL 较简单地完成;
二、过程
1. 复制序列
由于需要重新对原数组赋值,则不能直接在原数组上操作,所以先复制一个数组 c c c 用于离散化;
int c[MAXN];
memcpy(c, a, sizeof(a));
2. 排序,去重
由于要将元素在数组中的排名作为其新的排名,所以先使用 s o r t sort sort 对原数组进行排序;
又由于要计算排名,所以使用 u n i q u e unique unique 进行去重;
定义 l l l 为所有不重复的元素数量;
sort(1 + c, 1 + c + n);
int l = unique(1 + c, 1 + c + n) - c - 1;
由于 u n i q u e ( ) unique() unique() 的返回值是一个迭代器,表示去重后容器中不重复序列的最后一个元素的下一个元素;
所以减去数组迭代器再减去 1 可得到原数组的不重复元素的个数;
3. 重新赋值
将 a a a 数组元素重新赋值为其在 a a a 中的排名,即其在 c c c 中的下标;
即可遍历 a a a 中的每个元素,每次二分查找当前的元素值在 c c c 位置,然后将其赋值为新的元素值即可;
for (int i = 1; i <= n; i++) {
a[i] = lower_bound(1 + c, 1 + c + l, a[i]) - c;
}
由于排序和 n n n 次二分查找的复杂度都是 O ( l o g 2 n ) O(log_2n) O(log2n) ,所以离散化的复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n) ;
三、代码
以将长度为 n n n 的数组 a a a 进行离散化后又存入 a a a 中为例;
void discret() {
memcpy(c, a, sizeof(a));
sort(1 + c, 1 + c + n);
int l = unique(1 + c, 1 + c + n) - x;
for (int i = 1; i <= n; i++) {
a[i] = lower_bound(1 + c, 1 + c + l, a[i]) - c;
}
return ;
}