进行数据离散化的原因_C++实用技巧——离散化

4a1d16a23dfefde22d1322c67a573e65.png

离散化是程序设计中一个常用的技巧,它可以有效的降低时间和空间复杂度。

离散化,就是把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。

打个比方:现在有一组很大的数据

1,23424,21472313246768,6594,95,0,65535313

如果将这些数作为数组的下标来保存对应的属性时,我们将需要开一个很大的数组。以上方数据为例,这个数组至少要开21472313246768这么大的空间,这样很多题目的空间限制这关都过不了了,怎么办呢?当数据只需表示出它们之间的相对大小关系,而不需表示出具体数值时,我们就要用一个小技巧——离散化。

还是以上面的数据为例,经过离散化处理后,数据就成了:

1,4,6,3,2,0,5

神不神奇,意不意外!!!

——不意外!!!

在这里,我就献上处理数据的程序,教大家如何实现。

第一种方法:

const int N=1e5+7;

int t[N],a[N];

int main()

{

cin>>n;

for(int i=1;i<=n;i++)

cin>>a[i],t[i]=a[i];

sort(t+1,t+n+1);

m=unique(t+1,t+n+1)-t-1;

for(int i=1;i<=n;i++)

a[i]=lower_bound(t+1,t+m+1,a[i])-t;

}

在这段代码中,a[]经过离散,范围就变成了m。解释一下,unique是c++自带的一个函数,表示对一个数列去重,然后返回不重复的元素个数,当然在后面要减去首地址。那么这种离散化对于有重复元素的数列也可以适用,但复杂度相对后面要讲的第二种方法会高些。

026e2c88f55025e8c18c031dc4dce87c.png

比如,这组数据:

1,23424,242,65466,242,0

进入这段代码后,首先会排个序得到:

0,1,242,242,23424,65466

然后会去重,得到:

0,1,242,23424,65466

然后离散化的到:

1,3,2,4,2,0

第二种方法:

const int N=1e5+7;

struct Node

{

int v,id;

bool operator < (const Node a)const

{return v

}a[N];

int n,rank[N];

int main()

{

cin>>n;

for(int i=1;i<=n;i++)

{

cin>>a[i].v;

a[i].id=i;

}

sort(a+1,a+n+1);

for(int i=1;i<=n;i++)

rank[a[i].id]=i;

}

这种方法复杂度比上面那一种要优,但不能处理重复元素。它直接用结构体存储原本的数列的元素的位置,然后排序以后将他们再重新赋值。那么rank[]就是结构体a[]离散化后的结果。

v: 3 6 5 10 8

id : 1 2 3 4 5

排序以后:

v: 3 5 6 8 10

id: 1 3 2 5 4

所以离散化以后:

v: 3 5 6 8 10

id: 1 3 2 5 4

rk: 1 2 3 4 5

在按原来的顺序排列:

v: 3 6 5 10 8

rk: 1 3 2 5 4

今天的讲解就到了这里,相信大家对离散化有一定的了解了。

feec14a036a4e3bcb16cbddd3df3de55.png

最后,学习从来不是一个人的事情,要有个相互监督的伙伴,对于C/C++感兴趣可以关注小编在后台私信我:【编程】一起来学习哦!可以领取一些C/C++的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值