数据离散化
1. 离散化概述
离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
原数据:1,999,100000,15;处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};
个人理解
其基本思想就是在众多可能的情况中,只考虑需要用的值。
离散化可以改进一个低效的算法,甚至实现根本不可能实现的算法。
离散化可以改变元素之间的相对大小,不改变他们的大小关系。
这种做法往往可以节省空间,减低时空复杂度。
举个例子~~
比如说,当你想要开辟一个数组,并且需要通过数组的下标值来表示当前的数据,且你只会用到数据之间的相对大小关系时,如果数据特别大例如序列:1 3 999 210 220,如果想开辟一个大小为220的数组显然是不可能的,这时就可以使用数据离散化,例如可将原序列离散化为:1 2 3 4 5,它们之间的相对大小关系是不发生改变的。
这相当于是通过映射关系,将大范围里面很少的数据进行小范围存储,压缩了使用空间。
需要注意的是,离散化仅适用于只关注元素之间的大小关系而不关注元素本身的值!
2. 应用场景
有些数据本身很大, 自身无法作为数组的下标保存对应的属性。
如果这时只是需要这堆数据的相对属性, 那么可以对其进行离散化处理。
当数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。
3. 实现方法
下面给出数据离散化常用的一般步骤:
1. 对数据进行排序
2. 对数据进行去重
3. 离散化数据处理
4. STL函数说明
4.1 lower_bound
基于二分查找,返回指向首个不小于 value 的元素的迭代器,或若找不到这种元素则为 last 。.
参数说明:
- first:首元素迭代器
- last:尾元素的下一元素迭代器
- value:查找值
4.2 unqiue
从来自范围 [first, last) 的相继等价元素组消除首元素外的元素,并返回范围的新逻辑结尾的尾后迭代器。
通过用覆写要被擦除的元素的方式迁移范围中的元素进行移除。保持剩余元素的相对顺序,且不更改容器的物理大小。
即元素去重操作,这里是伪去重,只是将重复元素放到存储空间的最后,不去遍历则可视为没有,返回新结尾的迭代器。
4.3 sort
以升序排序范围 [first, last) 中的元素。不保证维持相等元素的顺序。
4.4 erase
从容器擦除指定的元素。
- 移除位于 pos 的元素。
- 移除范围 [first; last) 中的元素。
5. 代码描述
5.1 数组
//离散化数组
int arr[100000];
int main(){
int n;
cin>>n;//输入元素个数
for(int i = 0;i<n;++i)
cin>>arr[i];
// 1. 排序 左闭右开
sort(arr,arr+n);
cout<<endl<<"数组原始序列:";
for(int i = 0;i<n;++i)
cout<<arr[i]<<" ";
cout<<endl;
// 2. 去重unique
int length = unique(arr,arr+n) - arr;
//length为离散化后数组的有效长度
cout<<endl<<"去重后的序列长度为:"<<length<<endl;
cout<<endl<<"去重后的序列:";
for(int i = 0;i<length;++i)
cout<<arr[i]<<" ";
cout<<endl;
// 3. 离散化
for(int i = 0;i<length;++i)
arr[i] = lower_bound(arr,arr+n,arr[i]) - arr;
cout<<endl<<"离散化后的序列:";
for(int i = 0;i<length;++i)
cout<<arr[i]<<" ";
cout<<endl;
return 0;
}
5.2 vector容器
//离散化vector
int main(){
vector<int>v;
int n;
while(cin>>n){//输入数据
v.push_back(n);
}
// 1. 排序
sort(v.begin(),v.end());
cout<<endl<<"数组原始序列:";
for(int i = 0;i<v.size();++i)
cout<<v[i]<<" ";
cout<<endl;
// 2. 去重unique
v.erase(unique(v.begin(),v.end()),v.end());
//length为离散化后数组的有效长度
cout<<endl<<"去重后的序列长度为:"<<v.size()<<endl;
cout<<endl<<"去重后的序列:";
for(int i = 0;i<v.size();++i)
cout<<v[i]<<" ";
cout<<endl;
// 3. 离散化
for(int i = 0;i<v.size();++i)
v[i] = lower_bound(v.begin(),v.end(),v[i]) - v.begin();
cout<<endl<<"离散化后的序列:";
for(int i = 0;i<v.size();++i)
cout<<v[i]<<" ";
cout<<endl;
return 0;
}
6. 执行结果
7
1 2 2 4 3 5 1
数组原始序列:1 1 2 2 3 4 5
去重后的序列长度为:5
去重后的序列:1 2 3 4 5
离散化后的序列:0 1 2 3 6
Process returned 0 (0x0) execution time : 15.000 s
Press any key to continue.
999 1 3 4 4 99 9999 999 100000 5 ^Z
数组原始序列:1 3 4 4 5 99 999 999 9999 100000
去重后的序列长度为:8
去重后的序列:1 3 4 5 99 999 9999 100000
离散化后的序列:0 1 2 3 4 5 6 7
Process returned 0 (0x0) execution time : 17.407 s
Press any key to continue.
——————END-2022-05-12——————