java 变位词,[Java教程]变位词的查找(下)

[Java教程]变位词的查找(下)

0 2017-04-09 12:00:46

本文也同步发表在我的公众号“我的天空”

bc91bb04e6e9c61e24c974e4440db8f2.gif

实现方案优劣的思考

之前我们的实现方案的优点是一旦目标词库的签名建立后,则变位词的查找会变得简单而快速;缺点是由于在生成目标词库时,要为每个词都生成签名,导致生成词库的时间会变慢,同时会消耗空间。对于那些没有被查找到的字符串的签名实际上是浪费的。

测试结果:在CPU为Inter Core i3-2328M,内存为6GB的PC上生成数量为1万的目标词库平均时间为377毫秒,查找变位词的平均时间为11毫秒。

第二种方案

在生成目标词库的时候并不生成签名,而是在查找的时候生成签名。

function search(str){

var mathstr="";

for(var x in array_str){

//查找时生成签名,再判断签名是否相同

if(get_sign(str)==get_sign(array_str[x])){

mathstr+=mathstr.length==0?array_str[x]:","+array_str[x];

}

}

return mathstr;  //返回找到的变位词

}

测试结果:生成数量为1万的目标词库平均时间为130毫秒,查找变位词的平均时间为530毫秒。

该方案虽然提高了生成目标词库的速度,并节省空间,但是查找的速度太慢,与第一种方案相比较慢了约50倍。分析代码发现每次查找都需要为目标词库重新建立一遍签名,效率太过低下,考虑优化。

第二种方案的优化

针对第二种方案的不足之处,考虑做如下优化:如果两个词互为换位词,那么这两个词的长度必定相同,同时组成这两个词的字母的asscii编码之和也必定相同,因此在遍历目标词库时,首先判定这两个条件,如果满足则再获取其签名来作比较。获取字母的ascii编码采用charCodeAt()函数。

function search(str){

var mathstr="";

for(var x in array_str){

//如果两个词互为变位词,那么这两个词的长度和各字母的asciicode之和必须相同

if(str.length==array_str[x].length && get_asciicode_total(str)==get_asciicode_total(array_str[x])){

//查找时判断签名是否相同

if(get_sign(str)==get_sign(array_str[x])){

mathstr+=mathstr.length==0?array_str[x]:","+array_str[x];

}

}

}

return mathstr;

}

//获得字符串的ascii码之和

function get_asciicode_total(str){

var data=str.split("");

var i=0;

for(var x in data){

i+=data[x].charCodeAt();

}

return i;

}

经测试,优化后的查找速度平均为43毫秒,速度提升还是很有效果的!

总结

该题主要是偏向于对问题的思考、解决方案的制定、实现与选择、代码优化等方面,在实际工作中,往往一个问题的解决会有多套方案,大家应该学会从各方面来衡量、测试,最终选择解决的问题的最优方案。该题主要涉及到随机数的操作、排序算法的掌握、ascii编码的掌握。

当然,以上两种方案仍有优化的空间,对于第一种,可以考虑将签名数组按照签名来排序,这样就无需每次都遍历整个签名数组,如果生成的目标词库数量巨大,还可以考虑将签名数组分段索引,以便能更快的找到签名;对于第二种,可以将查找中已生成的签名保存下来,这样下次查找再遇到该字符串该就无需再生成签名了,因为在整个程序中,最影响性能的就是生成签名,我们应尽量减少生成签名的操作。

示例代码

https://github.com/panyongwow/anagram

本文网址:http://www.shaoqun.com/a/306839.html

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们:admin@shaoqun.com。

0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值