acm数据预处理 —— 离散化的两种方法

博客目录

引言

如果我们要处理一些数据,如果:

我们只关心数据之间相对大小,而不关心每个数据到底有多大

离散化的大体意思就是:给数据重新编号,使新号码依然具有跟之前相同的大小关系,来使数据更加紧凑。

比如说:给一个无向图,每个节点都以一个字符表示,那么我们就可以将字符替换成数字123...

再比如说:现在有1000个[-1e9,1e9]范围的整数,计数统计一下每个数出现的次数。由于开一个2e9大小的数组实在是太浪费空间了,而且只有一千个数,遍历2e9的时间开销也实在是浪费,所以我们可以根据原数据的相对大小重新编号,对编号进行计数,也也就达到了对元数据进行计数的目的。

方法1:排序加折半查找(nlogn的时间复杂度,我之前不太喜欢用的方法但是大家都用,代码比较精简,但是不易还原输入顺序)

 

    cin>>n;

    int co[1000];
    for(int i=0;i         cin>>co[i];
    }
    sort(co,co+n);
    int size=unique(co,co+n)-co;//去重函数,将重复的都移到后边,然后用size截掉,相同元素仅保留一个, 
                                //如果不需要去重则删掉这一句。size为离散化后元素个数 
    for(int i=0;i         arr[i]=lower_bound(co,co+size,arr[i])-co + 1;//arr存放了排序后,第i个数字新的编号。

方法2:捆绑排序,时间复杂度O(nlogn),老实说是我自己的土办法。如果想还原输入顺序直接对i在进行排序即可

struct inp{
    int i,v,n;
};

inp co[1000];

int operator<(inp a,inp b){
    return a.v }
int main(){
    int n;
    cin>>n;
    for(int i=0;i         cin>>co[i].v;
        co[i].i=i;
    }
    sort(co,co+i);
    for(int i=0;i         co[i].n=i+1; //n是新的标号,v是原始数据,i是原始数据的顺序,要去重另加代码
    }
}

你可能感兴趣的:(简单实用的算法/数据结构)