关于离散化

前言:

关于上周打的一场积分赛,b题为简单离散化之后dp就ok,但是比赛期间完全没想到离散化,导致TLE之后不会优化,就没写出来,赛后补完题,又去练了一些离散化的题,也算有了一点理解

离散化

所谓离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。

通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。

比如说题目需要对1,10,100,90000000,10101010101数据进行处理,如果不进行离散化处理那么就需要开大小为10101010101的数组保存操作结果,很明显无法实现,这时候就需要用到离散化处理数据。

代码实现

在网上的离散化处理代码一般都是排序,去重,索引的方法

const int N=2e5+5;
int n,a[N],t[N];
void solve()
{
    // 读入数据
    cin>>n;
    for (int i=1;i =n;i++)
    {
        cin>>a[i];
        t[i]=a[i]; //复制到 t中 
    }
    //对数组 t排序
    sort(t+1,t+1+n);
    //去重并获取去重后的数组大小
    int q=unique(t+1,t+1+n)-(t+1); 
    for (int i=1;i<=n; i++){
        // 映射
        a[i]=lower_bound(t+1,t+1+q,a[i])-t;
    }
    return ; 
}

但我是利用map来实现离散化,个人感觉更加好用一点

const int N=2e5+5;
int n,a[N],sum[N];    
void solve()
{
    for(int i=1;i<=n;i++)
        cin>>sum[N];
    sort(sum+1,sum+1+n); //排序,某些题目可能不需要
    map<int,int>mp; 
    int q=0;
    //a[++q]=0;    //把起点设为 0 
    for(int i=1;i<=n;i++)
    {
        if(!mp[a[i]]) //判重 
        {
            a[++q]=a[i];
            mp[a[i]]=q;    //记录索引 
        }    
    }
    //得到一个a数组,索引从1~q,用map查找索引
    return ;
}

map查找的时间复杂度为O (log (n)),如果需要优化时间还可以使用unordered_map,unordered_map插入和查询速度接近于O (1) 。但是如果对内存使用特别严格,需要程序尽可能少消耗内存,那么应该是用map,因为unordered_map占用内存较多。

unordered_map已经加到C++11标准(编译时添加编译选项:--std=c++11)

C++ STL unordered_map容器用法详解

map和unordered_map区别及其优缺点

#include<unordered_map> 
using namespace std;
//unordered_map使用的头文件 
const int N=2e5+5;
unordered_map<int,int>ump;
//unordered_map因为占用内存多,开在函数外 
int n,a[N],sum[N];
void solve() //别的部分和 map一样 
{        
    for(int i=1;i<=n;i++)
        cin>>sum[N];
    sort(sum+1,sum+1+n);
    int q=0;
    //a[++q]=0;    //把起点设为 0 
    for(int i=1;i<=n;i++)
    {
        if(!ump[a[i]])
        {
            a[++q]=a[i];
            ump[a[i]]=q;
        }    
    }
    return ;
}

总结

离散化是程序设计中一个常用的技巧,它可以有效的降低时间复杂度。其基本思想就是在众多可能的情况中,只考虑需要用的值。离散化可以改进一个低效的算法,甚至实现根本不可能实现的算法。要掌握这个思想,必须从大量的题目中理解此方法的特点。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值