一道有意思的题目
来源:互联网 发布:哈尔滨淘宝何时停运 编辑:程序博客网 时间:2024/05/16 19:27
在外刊 IT 评论上看到一篇有意思的文章,里面的一道算法题目为:
假设这有一个各种字母组成的字符串,假设这还有另外一个字符串,而且这个字符串里的字母数相对少一些。从算法是讲,什么方法能最快的查出所有小字符串里的字母在大字符串里都有?
比如,如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOM
答案是true,所有在string2里的字母string1也都有。如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOZ
答案是false,因为第二个字符串里的Z字母不在第一个字符串里。
原文作者的思路为:对于这种操作一种幼稚的做法是轮询第二个字符串里的每个字母,看它是否同在第一个字符串里。从算法上讲,这需要O(n*m)
次操作,其中n是string1的长度,m是string2的长度。就拿上面的例子来说,最坏的情况下将会有16*8 = 128次操作。
一个稍微好一点的方案是先对这两个字符串的字母进行排序,然后同时对两个字串依次轮询。两个字串的排序需要(常规情况)O(m log m) + O(n log n)
次操作,之后的线性扫描需要O(m+n)
次操作。同样拿上面的字串做例子,将会需要16*4 + 8*3 = 88加上对两个字串线性扫描的16 + 8 = 24的操作。(随着字串长度的增长,你会发现这个算法的效果会越来越好)
最终,我告诉了他一个最佳的算法,只需要O(n+m)
次操作。方法就是,对第一个字串进行轮询,把其中的每个字母都放入一个Hashtable里(成本是O(n)或16次操作)。然后轮询第二个字串,在Hashtable里查询每个字母,看能否找到。如果找不到,说明没有匹配成功。这将消耗掉8次操作 —— 这样两项操作加起来一共只有24次。不错吧,比前面两种方案都要好。
如果这样呢 —— 假设我们有一个一定个数的字母组成字串 —— 我给每个字母分配一个素数,从2开始,往后类推。这样A将会是2,B将会是3,C将会是5,等等。现在我遍历第一个字串,把每个字母代表的素数相乘。你最终会得到一个很大的整数,对吧?然后 —— 轮询第二个字符串,用每个字母除它。如果除的结果有余数,这说明有不匹配的字母。如果整个过程中没有余数,你应该知道它是第一个字串恰好的子集了。这样不行吗?
文章最后有些精彩评论:
除了用素数的方法,也可以用位图的方法,素数有个溢出的问题需要处理
位图的方法:
如果只有字母的话用26位的二进制数表示,
A:1000…00, B:0100…00, …, Z:0000…01
对字符串中的字符进行按位或操作,得到A和B两个子串的值,然后 A|B == A也就意味着包含。
原文地址: http://www.aqee.net/google-interviewing-story/
- 一道有意思的题目
- 一道很有意思的题目
- 一道有意思的C++题目
- 一道很有意思的题目
- 一道有意思的二进制用法的题目
- 百度很有意思的一道面试题目
- 一道有意思的CSS布局题目
- 一道很有意思的JAVA题目
- 分享一道很有意思的算法题目
- 分享一道很有意思的算法题目
- 一道很有意思的题目,计算sum
- 一道有意思的题目之Integer
- 鸽巢原理应用于一道十分有意思的题目
- hdu1426一道很有意思的题目:数独
- 看到一道有意思的题目——自增陷阱
- 有意思的一道题
- 一道有意思的题
- 有意思的程序设计题目
- 检测sql语句执行效率
- 项目管理--欲速则不达
- hdu 3007 最小包围圆
- 项目管理--众人拾柴火焰高
- VHDL语言中CASE语句使用注意
- 一道有意思的题目
- 最小顶点数就能覆盖所有边==二分图的最大匹配
- 项目管理--不知言,无以知人也
- flex 导出文件&导出图片&文件下载
- Lync Server 2013 标准版的DNS和端口要求
- IOCP是一整套高性能的IO操作异步模型
- error D8030:internal compiler error in
- JQuery与springmvc实现多个文件上传操作
- NYOJ 920 Trees