空间换时间--编程小绝招解决电话区号识别算法问题
空间换时间问题通常都是一个不大的问题里的一个不小的解决方案。首先要理解代码中函数的一个大致的代价,在输入比较固定,计算输出又比较费劲的时候,常常就是空间换时间发挥作用的时候了。通过几个简单的例子您就会了解。
在Base64编码过程中,将源字节按规则取位得到一定数量的0~63的数的数组,按规则需要将这些数一一对应固定转换成特定字母数字来得到输出字符串。如果用if……else……的方法,会非常麻烦,代码看起来也很低端不给力。于是就有这样的“空间”:
static const char *codes64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
转换的时候非常简单潇洒的用 codes64[x] 即可得到转换该得到的输出。
在算法密集型库当中经常会有类似这样高大上的定义,现在你是不是明白他的意义?
static const unsigned char map64[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255 };
输入是值为0~255的单字节值,输出 = map64[单字节值]. 非常简单不是吗~
再介绍一种实用的空间换时间,这是我运用在从电话拨号数字串中识别号码的国家码和区号码的算法当中,仅介绍原理,代码相信您了解原理后自然能做出来。
通常的做法考虑可能会做一个数据库,或者做一个xml、ini配置。不过光就处理识别问题,也就是流式分析识别开头的号码是不是国家码是不是区号码的问题,还可以有更高效的办法。
考虑有一个数据结构,也就是“空间换时间”当中的“空间”,它以10个szUnit字节为一组于是一组的字节数长度是szBlock,对应索引值有第0、第1、……第9这样十个位置。空间以不定数量的组串联而成。当处理输入如7935555555这样的号码时,从第一个组的[7]号位拿值idx,如果idx是1~254之间,代表需要继续分析,转移到idx组即p = (QbUnit*)(mBase + p[7]*szBlock);取[9]的值,类似的,需要继续移到下一个组再取[3]的值,此时会得到unitHit。这样最终得到并返回 793 这样一个分析出来的串。
typedef unsigned char QbUnit ; //最小基本单元的尺度
//typedef unsigned short QbUnit;
#define szUnit sizeof(QbUnit) //基本单元的长度
#define szBlock (szUnit*10) //组长度
#define unitHit ((QbUnit)(-1)) //代表命中的值
可能您看过之后会有诸多疑问,如
- idx是相对值还是绝对值?
- 中国那么多区号250个以内的组就能够用吗,QbUnit是不是要用short两字节?
- 会不会有重码(即793和79区号并存导致无法识别和表示79区号)?
- 国际区号用这套行不行?
首先,idx是绝对值,组的起始位置就是pGs[idx]=从空间起始地址+idx*szBlock的地方,非常简单。我同样也考虑过当空间不够用新组在255之后的情况下用相对值会好一些,但是这种情况下,会存在不预期的情况。所以假如能确定不会超250组,就可以放心的用绝对idx。那么顺推到第2个问题,中国那么多区号,250个组足够了!QbUnit可以放心的用char(1字节单位)。举个例子您分析一下,中国所有区号只有2位的城市(不包括开头0)10=北京|21=上海|22=天津|23=重庆|24=沈阳/抚顺/铁岭|25=南京|27=武汉|28=成都/资阳/眉山|29=西安/咸阳|20=广州,只用到3个组。第0组放首位,[1]、[2]有值,[1]指向第1组,[0]位命中北京。第0组[2]指向第2组,[0]没有[1]上海[2]天津[3]重庆…… 注意,上述命中只是简单的unitHit,并不包含地名信息。因为我们只处理识别问题,如何显示还需要考虑国际化问题。
会不会有重码?不会!为什么那么笃定?因为电信系统也是用类似方法来处理号码的,电信系统为了能在有限功能的电话交换机上高效快速的处理电话拨号,不能做太复杂的编码规则,所以赫夫曼编码就成了编码的基础,它是不可能同时有79和793这样的区号的。当然这些是我的推论,没有查证权威资料。但是我发现国际码也是一样的情况。我写了一个工具按照我的规则将国际码和中国的区号码都做了生成,输出刚才说的数据结构“空间”,在代码中做了不少的断言(assert)。最终结果是并没有违背断言的情况发生。我做好的中国编码输出字节580,即58个组就搞定了。
空间换时间--编程小绝招解决电话区号识别算法问题相关推荐
- FPGA之道(62)时空变换之空间换时间
文章目录 前言 时空变换之空间换时间 缓存提速使用 模块复制 同频模块复制 缓存降频复制 缓存降频使用 逻辑拆分 流水线 流水线的由来 如何在组合逻辑中使用流水线 如何在时序逻辑中使用流水线 顺序系统 ...
- 前端遍历导致查询数据时间过长_OLAP 服务器,空间换时间可行吗?
[摘要] 全量预汇总真的是提高 OLAP 性能的可行方案吗?点击了解OLAP 服务器,空间换时间可行吗? 多维分析提供拖拽.旋转.切片.钻取等等人机交互操作,必须有秒级的响应速度.而这些操作对应的明细 ...
- 以空间换时间——动态规划算法及其应用:矩阵链相乘
动态规划算法是5大算法基础中最重要的一个,它专门用来解决平面世界下的应用,即会多次使用二维数组. 当然动态规划算法是空间换时间的算法,也就是说:我们可以利用空间资源来使某算法问题的时间复杂度降到最低. ...
- leetcode-383-Ransom Note(以空间换时间)
题目描述: Given an arbitrary ransom note string and another string containing letters from all the magaz ...
- 空间换时间,查表法的经典例子
前言 上一篇分享了:C语言精华知识:表驱动法编程实践 这一篇再分享一个查表法经典的例子. 我们怎么衡量一个函数/代码块/算法的优劣呢?这需要从多个角度看待.本篇笔记我们先不考虑代码可读性.规范性.可移 ...
- 空间换时间--程序策略
这几天修改一个去年做的程序,因为程序使用了xml保存的一些数据,整个xml文件结构欠佳,所以每次都需要对数据进行读取运算重新组合才能使用. 朋友需要这个程序多加点功能,于是顺便把这个去年做的不太好的地 ...
- 提高FLASH的擦写次数 “空间换时间”
提高FLASH的擦写次数 一.平时正常的读写,及损耗 二. "空间换时间" 三.数据结构 一.平时正常的读写,及损耗 Flash操作是往里面写0,按照平时的逻辑,每次参数发生了改变 ...
- [hashmap|空间换时间] leetcode 1 两数之和
[hashmap|空间换时间] leetcode 1 两数之和 1.题目 题目链接 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下 ...
- ie浏览器查看vue中js_浅析 Vue.js 中那些空间换时间的操作
Hello,各位小伙伴,接下来的一段时间里,我会把我的课程<Vue.js 3.0 核心源码解析>中问题的答案陆续在我的公众号发布,由于课程的问题大多数都是开放性的问题,所以我的答案也不一定 ...
最新文章
- linux查找技巧: find grep xargs amp;amp; linux系统信息查看大全
- php人工智能客服,人工智能技术在客服中心的四大应用
- easyui 收费_收费班长喻玉华三尺岗亭献青春
- 前端与移动开发乐淘项目-day02
- 福气太薄,刚积攒了点又被自己扔了
- php tcp获取数据_php建立tcp服务请求数据双向通信问题
- 写c++好的软件_族谱家谱制作怎么写?专业的家谱族谱编辑制作软件哪个好
- 实现 ASP.NET Core WebApi 的版本化
- linux 无线ap模式,在Linux(CentOS)上开启小度WIFI无线AP模式
- Mysql数据库简单回滚操作
- 2010年度总结-在淘宝的半年日子
- 魔改大西瓜源码下载之后画面显示只有一半的解决方法
- 萌新带你开车上p站(二)
- linux打包文件夹命令
- Unity 3D-- 摄像机Clear Flags和Culling Mask属性用途详解
- 开源协议之Code Project Open License (CPOL)
- 计算机二维动画实验原理,浅析计算机二维动画制作
- 贴息政策打出“组合拳”,院校实验室建设攻略来了(二)!
- 台式计算机除尘方法,台式电脑除尘方法 让你的电脑焕然一新
- SQL SERVER练习题及答案2
热门文章
- 百度地图--展示行政区划(省市区县)和添加多个标注点案例
- 信号与系统中冲激函数匹配法怎么理解
- python中ljust的意思_python中ljust什么意思
- CUDA:CUDA out of memory. Tried to allocate 100.00 MiB (GPU 0; 15.78 GiB total capacity; 14.24 GiB al
- 启动jenkins解锁后,报错“Failed to update the default Update Site 'default'”
- Vue组织架构树图组件vue-org-tree的使用
- ubuntu16.04解决耳机没有声音
- 《看板实战》读书笔记 XMIND版本
- python变量名必须以字母或下划线开头不区分字母大小写_Python 变量名必须以字符或下划线开头,并且区分字母大小写。_学小易找答案...
- 日记500字初中计算机课,日记500字初中日常生活