1.离散化的概念
给出一列数字,在有些情况下,我们只需要知道这些数的相对大小,而不关心这些数字的绝对大小,比如,对一个班级的学生成绩进行排名,我们最终只要排名就可以,不需要关心其成绩的绝对值。
“离散化”就是用数字的相对值代替它们的绝对值。离散化是一种数据处理技巧,它把分布广泛的数据转换为密集分布,从而能够让算法更快,更省空间地处理。
离散化的步骤如下:
1.排序,首先对数组元素排序,这样我们才能确定相对大小。
2.离散化,把排序后的元素从1开始逐个分配数值,完成离散化。
3.归位,把离散化的每个元素放回到原始位置,结束。
离散化的编码比较简单,可以自己编码或者借用STL中的函数。
这里先简单说一些STL中的函数:它们分别是lower_bound()(实现离散化)和unique()(去除重复元素),lower_bound函数的功能是在有序的数列中查找某个元素的相对位置,这个位置正好是做离散化时元素初值对应的新值。但是遗憾的是这类函数只适用于一维数组的离散化,也就是说,类似于结构体,二维坐标之类的数据就不行了,这里我们以自己编码实现离散化为主,在后面的进阶中我会继续深入分析离散化的应用。
2.离散化的手工编码
我们还是以例题的形式来展现其实现方式,方便理解和掌握:
2.1 人物风云榜
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
struct node {
int id, val;//id为元素的位置,val为元素的值
}olda[maxn];
int newa[maxn];
int n;
bool cmp(node a, node b)
{
return a.val > b.val;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%d", &olda[i].val);
olda[i].id = i;
}
sort(olda + 1, olda + n + 1, cmp);
for (int i = 1; i <= n; i++)
{
newa[olda[i].id] = i;//这个元素的位置原来在olda[i].id,把它赋值为i,i是离散化后的新值
if (olda[i].val == olda[i - 1].val)
newa[olda[i].id] = newa[olda[i - 1].id];//若两个元素原值相同,则把新值赋值为相同
}
for (int i = 1; i <= n; i++)
printf("%d ", newa[i]);
printf("\n");
return 0;
}
2.2点的离散化
这个题的特点是不用去重,少了一个步骤,
#include <bits/stdc++.h>
#define maxn 1000005
using namespace std;
struct node {
int id, x,y;
}olda[maxn];
int newa[maxn];
int n;
bool cmp(node a, node b)
{
if (a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &olda[i].x,&olda[i].y);
olda[i].id = i;
}
sort(olda + 1, olda + n + 1, cmp);
for (int i = 1; i <= n; i++)
{
printf("%d %d\n", olda[i].x, olda[i].y);
newa[olda[i].id] = i;
}
for (int i = 1; i <= n; i++)
printf("%d ", newa[i]);
printf("\n");
return 0;
}
相信这两道题能让你初步了解离散化了,离散化是一个基本技巧,应用很多,这里先不展开讲解了,后续也会加急跟进后续的进阶学习,你的点赞是对up最大的支持......(咳咳,串台了~~~)其实只要是能一个人的文章里学到东西,写这些东西就有意义,我更喜欢凭本事拿到点赞的博主,作为菜狗的我自然还有很长的路要走,初阶的认知概念,还希望大佬勿喷~~~
3.金句省身
接受自己的普通,然后拼尽全力去与众不同,不想输不需要理由,山茶花遇见贵人也会开放,滴水的日积月累也会穿石,只要自己不怕输,不认输,就不是理由。