05 2011 档案
摘要:上周末, 新鲜出炉的.已知一个字符串, 只含常见可打印ascii字符以及空格和换行, 要求进行如下过滤:1, 过滤掉前导空白和后导空白;2, 中间的连续空白字符, 只保留一个;3, 删除换行前后的空白字符;题目不难, 不过按照微软一贯的作风, 这种题目的目的不是在于考察学生会不会写程序(当然, 要是写不出就不太好了), 而是在于考察学生是不是能够考虑到方方面面的问题, "于细微处见功力".本着"测试先行"的原则, 可以先从测试用例入手, 如下所示:// Test cases for leading & trailing spaces.char a
阅读全文
摘要:Data Deduplication:http://en.wikipedia.org/wiki/Data_deduplication数据备份或传输的时候,为了降低存储或带宽开销,做一下压缩是很经常的,这是用CPU的cycle换取存储或带宽。压缩算法已经有很多的,不再赘述。data deduplication是另一种意义上的压缩:通过文件之间或文件块之间的冗余,来进行去重(deduplication)。考虑qq邮箱的超大邮件,会有用户经历过,当上传一个超大文件的时候,经过本地计算以后,页面提示用户说这个文件在服务器上面已经有了,这样就可以不用重新上传了。这就是data deduplication
阅读全文
摘要:例如以下的代码片段:int add(int a, int b){ return a + b;}void my_test(int *val, int (*func)(int, int)){ int a = 100, b = 200; *val = func(a, b);}void my_test2(int *val, ...){ int a = 100, b = 200; int (*func)(int, int) = *(int (**)(int, int))(&val + 1); *val = func(a, b);}int main(int argc, char **argv){
阅读全文
摘要:对于无法全部放入主存的大数据集进行排序,用类似于归并排序的两趟多路外排序。第一趟,将数据集分为多个片段,每个片段都可以放入主存,则用qsort这样的主存排序算法进行排序,然后每个片段都写回外存(磁盘);第二趟,将各个片段进行归并。每次,从第一趟得到的已排序过的各个片段中取第一个,排序以后写入最终的排序文件。这一趟可以做一些优化,如每次从各个片段中取一个块,当某个片段中的块用完的时候就取下一块,而输出则是预留一定大小的输出缓冲区,满了以后刷到最终的排序文件。对通常的数据大小来说,两趟就够了。第一趟,所有数据都要读入和写出一次;第二趟,所有数据也要读入和写出一次。
阅读全文
摘要:还有一种经常使用的策略是bitmap.Bitmap本身也是一种hash-table, 只不过hash的结果恰好落在[0, sizeof_bitmap_in_bits]内. 因为hash到的每个slot只有一个bit,所以通常用作判断是否存在等bool型的问题.例子, 已知40亿个不重复的unsigned int, 如何判断一个整数在不在这40亿个整数里面?给定说unsigned int,其实是指定了元素的可能范围, [0, 2^32 – 1]中, 注意2^32=42,9496,7296, 大约是42亿.判断存在与否, 一个bit就够了,而记录所有的uint32_t, 4GB/8=512MB的b
阅读全文
摘要:问题:日志文件中, 寻找10个访问量最大的IP地址类似的变种还有:1, 搜索引擎搜索记录中, 寻找10个最热门的搜索词;2, 一个大文件里面, 寻找10个出现频率最高的单词;3, web proxy的记录里,寻找前10个访问最多的url;4, 对搜索引擎的搜索记录按照频率进行排序;5, 海量数据中,找到出现频率最高的一个;这些问题一般都要求数据无法完全放入内存, 要么强调数据有100G, 300G, 要么强调只能用1G内存什么的. 这么要求的目的在于避免被提问者直接走一遍统计一下完事.解决的思路是divide andconquer, 而divide的办法是对key或者元素进行hash, 然后分
阅读全文
摘要:如何选择合适的bitmap大小以及hash函数的个数?数学分析略,可参见wiki上面的页面(简单的概率论知识),结论如下:给定允许的错误概率p,以及元素个数n,总的bit数m应为:m >= -n*ln(p) / (ln2) / (ln2)譬如,如果给定错误率p为0.001,代入可得 m >= 14.4n给定n和m以后,选择多少个hash function也是一个问题,结论如下:hash函数的个数k应为:k = m * ln2 / n,也即 k = 0.7 * m / n.再次用上面的p=0.001的例子,m >= 14.4n, 那么k = 0.7 * 14.4 = 10如果p
阅读全文
摘要:拓扑排序:应用于DAG图。先遍历一遍(DFS、BFS),每个节点标记入度(in-degree)。入度 为0的节点,放入一个队列。初始时,该队列中的元素都是第一批的点(不依赖于任何其他元素);之后,弹出该队列中所有元素,将其后继结点的入度减一,如果后继节点入度降为0,则放入该队列。重复以上步骤,这样就分批次的标记上了依赖关系的排序。单源最短路径Dijkstra:是一个集合不断扩张和节点距离不断更新(减小)的过程,两个要点:如何更新节点的距离、如何选择下一个节点加入S。初始时,集合S仅包含源点s,其他节点的到源点的距离Dist设为无穷。将当前节点curr设为s之后,对当前节点s,如果s的某个邻居w
阅读全文
摘要:恰当安排可以减少比较次数,见下。求序列中最大数和最小数的时候,naive的做法(分别求)需要比较大约2n次。更好的做法是:假设易知max和min是前k个元素的最大和最小,那么,将k+1与k+2先比较一下,然后,大的和max比,得到新的最大;小的和max比,得到新的最小。这样,每向后走两个元素,只需要三次比较,最终的比较次数大约是3n/2次。求序列中最大的两个数,可以这么做:假设max1, max2是一个子集A的最大和次大元素,max3, max4是另一个子集B的最大和次大元素,那么,Union(A, B)的最大元素只可能是max1和max3中比较大的一个,假设max1>max3,那么次大
阅读全文
摘要:qsort的每一趟中,选定pivot以后,partition的过程如下:开始时,ptrLeft,ptrRight分别指向数组两端;*ptrLeft小于pivot时,向右走;*ptrRight大于pivot时,向左走;ptrLeft和ptrRight都走不动的时候,交换对应的元素,继续。ptrLeft和ptrRight相遇的时候,结束这一趟,然后二分的对两边继续qsort。更新:这样的做法需要处理各种特殊情况(略),因此更好的思路是:partition的时候,思路是:1,将pivot放到序列末尾;2,两个指针ptr_old_curr、ptr_new_curr从左向右扫描,如果*ptr_old_c
阅读全文
摘要:实质都在于找到相应的递推关系。对于n种物体k1-kn,大小为K的背包问题来说,递推关系是:P(n, K) = P(n-1, K) || P(n-1, K-kn),也即,根据当前物体kn是不是被选中,来二分。对于树的直径问题,记f(t)为以节点t为根的子树的直径,h(t)为以节点t为根的子树的高度,则f(t) = max{ f(left), f(right), h(left) + h(right) + 2 }对于叶子节点,f与h均为0,则递归关系找到了。对于集合的划分问题(一个整数集合,是否存在一种划分,使得两个子集合中元素的和相等),立刻可以转化为背包问题。
阅读全文
摘要:Bloom Filter是一种概率数据结构(probabilistic data structure),对外提供的是一个set的接口。参见http://en.wikipedia.org/wiki/Bloom_filter-----------------------------------------------------注:set、map这些,通常称作是抽象数据结构,也即它们只是规定了一组可能的操作作为其接口,而不限制内部的具体实现。set的接口通常包括:a) 元素与集合的运算,test for in or not in;b) 集合与集合的运算,intersection、union etc
阅读全文
摘要:假设集合A有n个元素,集合B有m个元素,两个集合取自某个空间(universe)。1.1, 首先从最naive的办法开始。对B中元素,挨个测试是不是在A中,交集、并集都是O(m*n),平方级别的算法。1.2, 将A先排序,O(n*logn),然后,对B中元素,挨个测试是不是在A中,这时可以二分了,O(m*logn),一共是O(n*logn)+O(m*logn)=O((m+n)*logn)。所以如果m<n的话,对调一下A和B比较好,也就是复杂度是O( (m+n) * log( min(m, n) ) ).这种思路的本质是,只利用了“A是集合”这个事实,然后对B中元素进行is in A的测试
阅读全文
摘要:block cipher已经有很多了,3DES、blowfish、AES...加密算法给出的是:给定key和plaintext,如何变换得到ciphertext。从加密算法开始,如何得到一个加密文件的可用程序,还有一段路要走,主要面对的问题是:1,从文件到plaintext,文件的大小通常不是一个block大小,那么,如何分块,不同块之间如何处理,如果不能分成完整的块怎么办?2,从口令(password或者passphrase)到key,用户的加密解密口令通常是一个字符串,如“fotally”,怎么从口令得到一个key?RSA Labs的标准PKCS#5,给出了一些推荐做法,见http://w
阅读全文
摘要:问题场景:我们有一块设备卡,上面跑着一个FreeBSD。host这边是Linux,与device那边的交互由host这边的Linux driver负责,driver在Linux下提供了几个char device来使得用户可以与device交互。这些char devices里面,有一个连接到device那边FreeBSD的终端,host端通过minicom(一个2222old的Unix程序)来通过这个char dev与device端交互,这样方便device一端的开发调试。问题:这个char device只能由一个进程来使用。那么,如果两个开发人员在同时进行开发,那么就只能在用的时候打开,用完就
阅读全文
摘要:The purpose of the algorithm is, given a curve composed of line segments, to find a similar curve with fewer points. The algorithm defines 'dissimilar' based on the maximum distance between the original curve and the simplified curve. The simplified curve consists of a subset of the points t
阅读全文
摘要:compile time assert:#define UNIQUE(x) __unique_name##x#define STATIC_ASSERT(expr) typedef char UNIQUE(__LINE__)[(expr)?1:-1];
阅读全文
摘要:False sharing is an inherent artifact of cache coherence protocols (like MESI and MOESI). It happens when two participants (threads) operates on different part of the same cache-line. Seehttp://en.wikipedia.org/wiki/False_sharingfor more details (and sample code).
阅读全文
摘要:#pragma GCC poisonRemove the specified identifier(s) from the program (and forbid them from appearing).Seehttp://gcc.gnu.org/onlinedocs/gcc-3.2.3/cpp/Pragmas.htmlfor more information.
阅读全文
摘要:__func__, __FUNCTION__, __PRETTY_FUNCTION__In C++, __PRETTY_FUNCTION__ contains the type signature of the function.Seehttp://gcc.gnu.org/onlinedocs/gcc-4.5.2/gcc/Function-Names.htmlfor more information.
阅读全文
摘要:Quoting APUE2:The mutex passed to pthread_cond_wait protects the condition. The caller passes it locked to the function, which then atomically places the calling thread on the list of threads waiting for the condition and unlocks the mutex. This closes the window between the time that the condition
阅读全文
摘要:场景:不小心删除了某文件,但该文件之前被某进程(譬如一个daemon)打开尚未关闭。注:文件删除是在打开的fd都关闭以后发生的,即,unlink一个文件以后,如果inode的引用计数降到0,这个文件应该被删除,但如果还有进程打开了这个文件且尚未关闭(即打开计数不为0),那么文件将在最后一个打开该文件的进程关闭该文件的fd以后删除。这也是为什么会有install这种命令的缘故。install会首先unlink文件,之后以同样文件名open(其实是create)该文件并写入;与之对应的是,cp命令打开文件直接写入。在install最常用的场合,安装新版本的共享库.so文件,由于要更新的.so文件可
阅读全文
摘要:Encrypted Salt-Sector Initialization Vector,自Linux Kernel 2.6.10引入的接口,用于产生安全的iv,公式如下:IV(sector) = Es(sector), where s = hash(key)参见wiki的页面http://en.wikipedia.org/wiki/Disk_encryption_theory#ESSIV
阅读全文
摘要:AES加密算法, 不说了。block cipher的各种工作模式,ECB、CBC、Counter等,不说了。Block Cipher在用作disk encryption的时候,也有许多问题要考虑。主要是ECB模式不行(很明显),CBC模式也不好(无法随机访问),所以IEEE标准化了一个P1619标准,IEEE Standard for Cryptographic Protection of Data on Block-Oriented Storage Devices,见http://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=449
阅读全文
浙公网安备 33010602011771号