试着解一道腾讯面试题
来源:互联网 发布:linux 查看端口号 编辑:程序博客网 时间:2024/06/02 16:25
帖子问题:
http://topic.csdn.net/u/20081029/22/C8FE34C1-25AB-4B94-986E-4C2FD4CAA664.html
(同学去面试的)
1、设计一个魔方(六面)的程序。
2、有一千万条短信,有重复,以文本文件的形式保存,一行一条,有重复。请用5分钟时间,找出重复出现最多的前10条。
3、收藏了1万条url,现在给你一条url,如何找出相似的url。(面试官不解释何为相似)
想了一中午,写了一下午(真服了自己,这么钻牛角尖,汗~),成果如下:
[原创] 解答一下吧,不知道看的算不算晚。
第1题:就是个数组和发生上下左右移动时候相关的数据变换问题;
第3题:正则表达式的应用问题,还涉及到一些思路问题;
重点第2题,我的解法如下:
思路:由于大量的数据,同时基于存储条件限制,尽量利用二分法,然后采用hash/binary结构,尽量避免循环。
------------------------------ Logic & Steps ------------------------------
/*
* 1. 对于1000万条存储在[硬盘, 文本文件]的短信记录,则设-> n = 10,000,000 (10 million)
* 2. 已知一条短信的长度是0 - 70 字符之间(最多70个字母,35个汉字),则设-> ArrayList<ArrayList> SMS[70] (1-70个不同长度,空短信另计)
*
* 3. 取 (第一个) 字符的[最后一位(bit)],为其建立-> ArrayList<ArrayList> bitFirstChar (取值0, 1)
* 4. 取 (最后一个) 字符的[最后一位(bit)],为其建立-> ArrayList<ArrayList> bitLastChar (取值0, 1)
* 5. 取((长度+1)除2) 字符的[最后一位(bit)]((i+1)/2),为其建立-> ArrayList<Dictionary> bitMidChar (取值0, 1)
*
* 6. 检查 (第一个) 字符[byte],为其建立-> Dictionary hashFirstCharacter<char, Dictionary> (首字相同放一起)
* 7. 检查 (最后一个) 字符[byte],为其建立-> Dictionary hashLastCharacter<char, Dictionary> (末字相同放一起)
* 8. 检查 ((长度+1)除2) 字符[byte],为其建立-> Dictionary hashMidCharacter<char, Dictionary> (中间字相同放一起)
*
* 9. 全文[String]比较,为其建立-> Dictionary hashSMS<String, long> (最终计数)
*
* 10. 维持一个全局 Dictionary<String, long> topSMS 遍历检验topSMS[i]中计数最小的String和当前更新的hashSMS[String]的大小,小则替换,否则无操作?或者最后再检查取前十???(这个我没考虑哪个时间开销更小)
*/
------------------------------ Logic & Steps ------------------------------
- /*
- * TopMostSMSReader pseudocode (C# version)
- * This is a demo for Reading top most SMS (or alike) Strings from files. partial code are pseudocode
- *
- * Author: Leemax Li
- * Created: 2008.11.03
- * MSN: leemax@live.com ; QQ: 735291192
- * Email: 1850018@qq.com
- * Last Modify: 2008.11.03 by Leemax Li
- */
- public class LeemaxTopMostSMSReader implements IDisposable {
- // global variables
- private int _fetchTotal;
- private Dictionary<String, long> _topSMS;
- private long _topTotal, _emptySMSCount;
- private long _totalCount;
- private bool _isUnderGo;
- // constructor
- public LeemaxTopMostSMSReader() {
- _fetchTotal = 10; // default number of sms fetched
- _topSMS = new Dictionary<String, long>;
- _topTotal = 0; // low efficiency
- _emptySMSCount = 0;
- _totalCount = 0;
- _isUnderGo = false; // lock flag, preserved for further use?
- }
- // main entry
- public Dictionary<String, long> CheckNow(String fileName, long maxLine) {
- // local variables
- FileHandle fileSrc = open(fileName);
- String nowSMS = "";
- long currentCount;
- Dictionary hashSMS<String, long>;
- Dictionary hashMidCharacter<char, Dictionary>;
- // ..... initial all members mentioned above
- // for (bit series) ... for(character series) ... for(hashSMS) ...
- // ...........................................
- // ...........................................
- try {
- // TryLock(this); // signal sync....
- _isUnderGo = true;
- while (nowSMS = fileSrc.ReadNextLine()) {
- _totalCount++; // total counter increament
- // condition checks, return if already no valuable candidates
- // if need precise number, just block these checks
- // low efficiency, useless....
- // if (maxLine > 0 && _topTotal * _fetchTotal > maxLine) return _topSMS;
- // an empty sms string
- if (nowSMS = EMPTY) {
- _emptySMSCount++;
- currentCount = _emptySMSCount;
- //CheckTopSMS(___EMPTY_, currentCount); // low eficiency
- continue;
- }
- if (SMS[nowSMS.length].bitFirstChar[0 or 1].bitLastChar[0 or 1].bitMidChar[0 or 1].hashFirstCharacter[nowSMS[0]].hashLastCharacter[nowSMS[nowSMS.length - 1]].hashMidCharacter[nowSMS[(nowSMS.length + 1) / 2]].hashSMS.HasKey(nowSMS))
- {
- SMS[nowSMS.length].bitFirstChar[0 or 1].bitLastChar[0 or 1].bitMidChar[0 or 1].hashFirstCharacter[nowSMS[0]].hashLastCharacter[nowSMS[nowSMS.length - 1]].hashMidCharacter[nowSMS[(nowSMS.length + 1) / 2]].hashSMS[nowSMS].Value += 1;
- }
- else
- {
- SMS[nowSMS.length].bitFirstChar[0 or 1].bitLastChar[0 or 1].bitMidChar[0 or 1].hashFirstCharacter[nowSMS[0]].hashLastCharacter[nowSMS[nowSMS.length - 1]].hashMidCharacter[nowSMS[(nowSMS.length + 1) / 2]].hashSMS.Add(nowSMS, 1);
- }
- //currentCount = SMS[nowSMS.length].bitFirstChar[0 or 1].bitLastChar[0 or 1].bitMidChar[0 or 1].hashFirstCharacter[nowSMS[0]].hashLastCharacter[nowSMS[nowSMS.length - 1]].hashMidCharacter[nowSMS[(nowSMS.length + 1) / 2]].hashSMS[nowSMS].Value; // low efficiency
- //CheckTopSMS(nowSMS, currentCount); // low efficiency
- }
- CheckOutTops();
- }
- catch (Exception ex) {
- // blah...blah...blah...
- }
- finally {
- // UnLock(this); // signal sync...
- _isUnderGo = false;
- }
- return _topSMS;
- }
- private void CheckOutTops() {
- // blah...blah...blah...blah...
- }
- // this is not good, should check out after all cleared out
- /*
- private void CheckTopSMS(String newString, long newCount) {
- long currentSmallest = _topSMS[0].Value;
- long currentString = _topSMS.Keys[0];
- foreach (KeyValuePair<String, long> currentPair in _topSMS) {
- if (currentPair.Value < currentSmallest) {
- currentSmallest = currentPair.Value;
- currentString = currentPair.Key;
- if (currentString == newString) {
- _topSMS[newString].Value = newCount;
- return;
- }
- }
- }
- // no match found, check the smallest
- if (currentSmallest < newCount) {
- if (_topSMS.Items.Count >= _fetchTotal) _topSMS.Remove[currentString];
- _topSMS.Add(newString, newCount);
- }
- }
- */
- // implementation of IDisposable
- public void Dispose() {
- // dispose all members here...
- // delete .... delete .... delete ....
- }
- // attributes and others
- public int ReturnLength
- {
- get { return _fetchTotal; }
- set { if(!_isUnderGo) _fetchTotal = value; else throw new Excetion("....."); }
- }
- public long CurrentLine
- {
- get { return _totalCount; }
- }
- public long CurrentEmptySMSCount
- {
- get { return _emptySMSCount; }
- }
- }
------------------------------ Possible Solution Code ------------------------------
------------------------------ analysis -----------------------------
- /*
- * 根据 Logic & Steps 中的设计
- * 1. N0 = 10,000,000 (10 million) (硬盘读取时间)
- * 2. SMS[70] (不需要遍历, N1 = 10 million / 71 < 140846)
- *
- * 3. 取 (第一个) 字符的[最后一位(bit)],bitFirstChar (CPU时间,不需要遍历, N2 = N1/2 < 70423)
- * 4. 取 (最后一个) 字符的[最后一位(bit)],(CPU时间,不需要遍历, N3 = N2/2 < 35212)
- * 5. 取((长度+1)除2) 字符的[最后一位(bit)]((i+1)/2),(CPU时间,不需要遍历, N4 = N3/2 < 17606)
- *
- * 6. 检查 (第一个) 字符[byte],hashFirstCharacter(首字相同放一起)(设为 M = N4)
- * 7. 检查 (最后一个) 字符[byte],hashLastCharacter(末字相同放一起)(设为X = N4/ln(N4))
- * 8. 检查 ((长度+1)除2) 字符[byte], hashMidCharacter(中间字相同放一起)(设为Y = N4/(ln(N4)*ln(X)))
- *
- * 9. 全文[String]比较,hashSMS(最终计数)(设为Z = N4/(ln(N4)*ln(X)*ln(Y)))
- *
- * 10. 维持一个全局 topSMS 遍历检验(每次检查为:N0*ln(FetchCount)次, 最后遍历 <= N4次)
- *
- * 时间代价为:O(Program): lnM*lnX*lnY*lnZ
- N = 10000000
- M = 71428.571428571428571428571428571
- lgM = 11.176453228349015489585363863205
- X = 6390.9873704292188700245451792576
- lgX = 8.7626440534989345490873775956615
- Y = 729.34462833478780320337939734221
- lgY = 6.5921463615017245913923031187162
- Z = 110.63841552338339979745756356137
- lgZ = 4.7062673662433216260688480137905
- Total Cost = lgM * lgX * lgY * lgZ
- = 3038.3836675663354054154917591655
- */
------------------------------- analysis ------------------------------
想了半个小时。。。写了半天~如果只是我自己“自我感觉良好”的话,也请看在我写了一下午6个小时的面子上不要喷我。
欢迎大家探讨~~~
* Author: Leemax Li
* Created: 2008.11.03
* MSN: leemax@live.com ; QQ: 735291192
* Email: 1850018@qq.com
* Last Modify: 2008.11.03 by Leemax Li
- 试着解一道腾讯面试题
- 一道腾讯面试题
- 一道腾讯面试题
- 一道腾讯面试题 .
- 一道腾讯面试题
- 一道腾讯面试题
- 腾讯一道面试题
- 腾讯的一道面试题
- 一道腾讯安全部面试题
- 腾讯的一道面试题
- 一道腾讯的面试题
- 腾讯的一道面试题
- 腾讯的一道面试题
- 腾讯的一道面试题
- 腾讯一道找中位数的面试题
- 一道腾讯公司的面试题
- 腾讯的一道Script面试题
- 一道腾讯面试题:英语单词拼写检查
- Servlet Action is not available 错误的其他可能原因和解决方法
- JAVA程序11.01
- 女孩最想男孩知道的事情
- Ajax 数据加载的实现
- 以下是三套目前Web 2.0网站流行试用的颜色元素
- 试着解一道腾讯面试题
- Cool Code list
- 项目设计
- 学习英语有用的网站(转自天涯)
- Cost
- 关于Tcp包出现CheckSum incorrect的问题
- 常用的功能测试方法
- 忙碌上班族实用保健有13招
- zz 正则表达式随笔