一、离散化简介
把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
离散化是一种将数组的值域压缩,从而更加关注元素的大小关系的算法。
当原数组中的数字很大、负数、小数时(大多数情况下是数字很大),难以将“元素值”表示为“数组下标”,一些依靠下标实现的算法和数据结构无法实现时,我们就可以考虑将其离散化。
e.g:
数组的范围是[1,1e9],而数组大小仅为1e5,那么说明元素值的“种类数”最多也就1e5,从而可以利用一个数组(离散化数组)来表示某个元素值的排名(即第几小),实现值域的压缩,将原数组的元素值作为下标处理。
离散化数组要求内部是有序的(一般是去重的,当然也存在不去重的方法,但是比较少见)的,可以直接通过离散化下标得到值,当然也可以通过值得到离散化下标(通过二分实现)
e.g:
原数组去重之后得到离散化数组,离散化数组实现一个映射,2->0,3->1,1000->2,99999->3
二、离散化的实现方法
#include<bits/stdc++.h>
using namespace std;
vector<int> L;//离散化数组
//返回x在L中的下标
int getidx(int x)
{
//lower_bound找第一个大于等于x的 -begin得到下标
return lower_bound(L.begin(),L.end(),x) - L.begin();
}
const int N = 1e5 + 9;
int a[N];
int main()
{
int n;cin >> n;
for (int i = 1; i <= n; ++i)cin >> a[i];
//将元素存入L数组中
for (int i = 1; i <= n; ++i)L.push_back(a[i]);
//排序去重
L.erase(unique(L.begin(),L.end()),L.end());
return 0;
}
三、代码示例
离散化不会单独考察,一般会结合其他算法或数据结构一起考察,例如树状数组、线段树、二维平面的计算几何等等。
e.g:
给定a数组,求a的离散化数组,并可以通过值找到下标。
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 9; int a[N]; vector<int> L; int getidx(int x) { return lower_bound(L.begin(),L.end(),x) - L.begin(); } int main() { int n;cin >> n; for (int i = 1; i <= n; ++i)cin >> a[i]; //将元素存入L数组中 for (int i = 1; i <= n; ++i)L.push_back(a[i]); //必须要先排序才能进行去重 sort(L.begin(),L.end()); //排序去重 //unique函数会把重复的元素添加到容器末尾,而返回值是去重之后的尾地址 L.erase(unique(L.begin(),L.end()),L.end()); cout << "离散化数组为:"; for(const auto &i : L) cout << i << ' '; cout << '\n'; int val;cin >>val; cout << getidx(val) << '\n'; return 0; }