数据离散化思想简述


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 。.

参数说明:

  1. first:首元素迭代器
  2. last:尾元素的下一元素迭代器
  3. value:查找值
    在这里插入图片描述

4.2 unqiue

从来自范围 [first, last) 的相继等价元素组消除首元素外的元素,并返回范围的新逻辑结尾的尾后迭代器。
通过用覆写要被擦除的元素的方式迁移范围中的元素进行移除。保持剩余元素的相对顺序,且不更改容器的物理大小。
即元素去重操作,这里是伪去重,只是将重复元素放到存储空间的最后,不去遍历则可视为没有,返回新结尾的迭代器。
在这里插入图片描述


4.3 sort

以升序排序范围 [first, last) 中的元素。不保证维持相等元素的顺序。
在这里插入图片描


4.4 erase

从容器擦除指定的元素。

  1. 移除位于 pos 的元素。
  2. 移除范围 [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——————

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苡荏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值