第一步 我们需要一个记录了所有原数据的数组,对其排序,去重。
然后第二步 另搞一个东西,使得我们可以从数据索引到离散化后的数
方法1:unordered_map
时间复杂度:就是无序的map,O(1)赋值(写作O(1),读作很慢)
空间需求:动态开,unordered_map内部消耗的空间咱也不清楚,应该不小
离散化->原数值:排序去重的数组a,a[离散化] = 实际值
方法2:开很大的数组
O(1)暴力赋值,dis[原数值]=离散化后数值(真正的O(1))
空间需求:需要开到原数据最大值那么大的范围,基本上1e7极限了
离散化->原数值:同方法1
方法3:比较常用的方法
int data[N];///辅助数组
void discrete(int *a,int n)
{
for (int i=0;i<n;i++) data[i] = a[i];
sort(data,data+n);
int cnt = unique(data,data+n) - data;
for (int i=0;i<n;i++)
a[i] = lower_bound(data,data+cnt,a[i]) - data;
}
时间复杂度:O(logN)找每个原数值在排序去重里的位置就是离散化后的数
空间需求:另开一个和原数组一样的数组就行,很棒
离散化->原数值:原数值数组保留就可以
像方法3空间需求比较小且可以对相同的值离散化成不同值的方法
就是解决上面因为二分查找位置导致所有数值相同离散化后只能赋值为同样的数字
原数组记为v,另外开一个指针数组*data指向原数组每个地址,然后按照指向元素的大小排序
排完序这个数组代表原数组中排名代表排名第几的数值的地址,那么显然data[i]-v就是那个数的下标,
所以一个for循环赋值:a[data[i]-v] = i.
复杂度还是O(n*logn)排序。然后O(1)赋值
离散化->原数据:v[data[i]-v],排第i对应的位置的值