博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
常用技巧——离散化
阅读量:6543 次
发布时间:2019-06-24

本文共 1089 字,大约阅读时间需要 3 分钟。

“离散化,就是把无限空间中有限的个体映射到有限的空间中去,以提高算法的时空效率。”

很多算法的复杂度与数据中的最大值有关,比如树状数组和纯用数组实现的一对一标记。时常会遇到这种情况:数据的范围非常大或者其中含有负数,但数据本身的个数并不是很多(远小于数据范围)。在这种情况下,如果每个数据元素的具体值并不重要,重要的是他们之间的大小关系的话,我们可以先对这些数据进行离散化,使数据中的最大值尽可能小且保证所有数据都是正数。

例如,有这样一个长为5的序列:102131511,123,9813186,-611,55。其中有非常大的数以及负数,会给许多算法的实现带来困扰,我们可以把这个序列离散化,使它变成这样:5,3,4,1,2。各个元素间的大小关系没有任何改变,但数据的范围一下子就变得很舒服了。

离散化的原理和实现都很简单。为了确保不出错且尽可能地提高效率,我们希望离散化能实现以下几种功能:1.保证离散化后的数据非负且尽可能的小2.离散化后各数据项之间的大小关系不变,原本相等的也要保持相等。由此,找出数据项在原序列中从小到大排第几就是离散化的关键。

可以通过下面的方法以O(nlong)的时间复杂度完成离散化,n为序列长度。

  1. 对原序列进行排序,使其按升序排列。
  2. 去掉序列中重复的元素。
  3. 此时序列中各位置的值和位置的序号就是离散化的映射方式。

例如:对于序列105,35,35,79,-7,排序并去重后变为-7,35,79,105,由此就得到了对应关系-7->1, 35->2, 79->3, 105->4。

代码如下:

int n, a[maxn], t[maxn];//这里以下标1为序列的起点,一般情况下从0开始也可以for(int i = 1;i <= n;i++){    scanf("%d", &a[i]);    t[i] = a[i];//t是一个临时数组,用来得到离散化的映射关系}//下面使用了STL中的sort(排序),unique(去重),lower_bound(查找)函数sort(t + 1, t + n + 1);//排序int m = unique(t + 1, t + 1 + n) - t - 1;//去重,并获得去重后的长度mfor(int i = 1;i <= n;i++){    a[i] = lower_bound(t + 1, t + 1 + m, a[i]) - t;//通过二分查找,快速地把元素和映射对应起来}

 

转载于:https://www.cnblogs.com/sun-of-Ice/p/9419857.html

你可能感兴趣的文章
程序员常用借口指南
查看>>
关于PXE网络安装linux系统中碰到的个别问题
查看>>
awk 常用方法
查看>>
Android网络框架实现之【Retrofit+RxJava】
查看>>
Android文件的加密与解密
查看>>
SOAP webserivce 和 RESTful webservice 对比及区别
查看>>
【原】记录一句话
查看>>
Android标题栏,状态栏
查看>>
Windows下安装Memcached for PHP
查看>>
hdu 1040 As Easy As A+B
查看>>
java笔记:SpringSecurity应用(二)
查看>>
php记录代码执行时间
查看>>
【C】strcpy()需谨慎使用;
查看>>
用Adobe Flash Professional CS6创建一个iOS应用程序
查看>>
简简单单几段代码让自己变成最合格的网站管理员
查看>>
Slim Text 0.0.9 发布, 代码开源!
查看>>
[置顶] 遵循Java EE标准体系的开源GIS服务平台之二:平台部署
查看>>
Session深度探索
查看>>
shell语法简单介绍
查看>>
Java递归算法——阶乘
查看>>