CCI 复习笔记 17

还是继续写吧,哈哈,今天下午面facebook呢


其实本来应该是做16章的,但是16章有点难,可能要多写很多代码,我觉得可能写17章比较不那么浪费时间。

刚刚salesforce打电话给我了,尼玛,又开始有点小后悔了。


17.1 In place swap two numbers


这题是我给女朋友出的题,a=a+b,b=a-b,a=a-b

或者a=a-b,b=a+b,a=b-a


书上给了一种牛逼的

a =a^b 

b=a^b

a=a^b


不想看了,看了也不会记住的。。。


17.2 tic-tac-toe判断谁会赢


没啥意思。主要的思想就是,到底是在做棋盘的时候就做一个对于谁会赢的维护。还是说每次再算一遍。


这个只要写过稍微大点的程序都会碰到的问题。我的感觉是,似乎永远是创建的时候就维护比较划得来


17.3 写一个程序计算一个number of trailing zeros in n!


这个程序要是企图算n!,就是扯逼了,必须要用big int, 我在我的英文博客上写过一个,麻烦是麻烦,但是也就是算而已。


我觉得这题的简单做法有好几种,最简单的似乎应该是用merge,每次找两个数字乘一下,把0去掉存起来,然后再继续这么做,然后一直算到底。问题是,不一定可以保证不会溢出


另外一个做法要麻烦很多,计算1:n里面有多少个10,多少个factor of 5, 以及多少个可以配对的偶数。。。。


然而书上用的是第二种方法,idea是这样,偶数出现频率要远远地高。。。。所以只需要计算有多少个因数5就行了。


17.4 不用if else 以及comparison operator,找到两个数里面比较大的那个


书上是bit manipulation。 基本上是max = a*f(a-b)+b*f(b-a), if a>b, f(a-b)=1 otherwise 0


但是大于号咋办呢?


flip((a>>31) & 0x1)


这个东西只能用补码完成,但是python怎么出补码呢?我还真的不知道。。。。


17.5 给你两组字符,A是机器产生的,B是用户猜得,要求给出有多少hit(位置也对),以及peudo-hit(位置不对)


天真的做法是先线性查找hit,做标记,再n^2查找peudo-hit,还得做标记。


第二部分可以用一个map,先记录A(不记录hit),再用B减,另外做个记录。书上也是这么做的


17.6 在一个数列里面,找到一个区间,sort了这个区间,整个array就sort了


首先这个算法肯定得小于 nlogn,不然直接sort之后match就解决问题(这样这题还有什么意义。。。)


n:m要满足的条件是前后都是sort的,而且n前的部分的最大值是小于n:m的最大值的,m后面的部分也满足这个类似的条件。


所以可以这么做先greedily找到head和tail,然后找到那个piece里面的max和min,如果min小于a[n-1],就把这个n往前推。


解决问题


17.7 给一个整数,print出大写的这个数字。


除了麻烦,没别的。这题的难度在于麻烦。


17.8 contiguous largest sum of an array


微软的初面,我的起点。哈哈哈


有很多种做法,现在看来一个DP并不容易解决问题,因为是coniguous的,所以要判断两个边界,但是判断两个边界就是2D DP,不大好


如果就用一个runner,不断加和,如果加和,在每一个加和都做记录,更新max,当前加和小于0的时候,就归零重新做加和。


这题特么现在看起来也没有这么简单啊,我当初居然不到十分钟就做出来了。


17.9 设计一个方法,可以找到一本书里面的高频词汇


hashmap


17.10 XML


略过,似乎很简单


17.11 用rand5 implemet rand7


如果0-4可以做的话,需要一个5-》7的map,显然至少得算两次。但是如何才能保证平均呢?


书上的做法是用5*rand5()+rand5, 为什么这个可以呢?首先5*rand5可以得到0,5,10,15,20,15

这几个数字,然后另外一个rand5就可以填下中间的空,然后把最后面的一点截掉


这题能理解这个数学问题就差不多了,我觉得。


17.12 找到一个array里面加和等于同一个数字的数对。


我的解法,排序之后两边收缩,O(n)


书上同时给出了一个更加简单的解法。用一个hashmap,同时检测sum-x


17.13 把一个BST in-place 地变成一个doubly linked list


 这个题目主要的难度,应该是搞出一套规则。


doubly linked list, 首先,一个node的左边的node,应该是它child的rightmost

一个node的右边也就是它第一个本身左孩子的parent (如果他本身是右孩子),或者它的parent,如果他本身是左孩子


或许比较简单的方法是直接使用in-order traversal, 但是写了半天也没有写对

原因是,我根本就不应该这么写。


基本上的idea是,

def convert(node)

if(node is None):

return None


head1, tail1 = convert(node.left)

head2, tail2 = convert(node.right)

real_head = node

real_tail = node


if(head1 is not None):

concat(tail1,node)

real_head = head1

if(head2 is not None):

concat(node,head2)

real_tail=tail2

return real_head, real_tail


书上的第三种方法是做出一个circulated linked list, 原因其实是在不用内存的情况下得到两个返回,这样看来似乎对于python来说并没有这个问题


17.14 假如你的文本里面的所有分隔都没有了,但是你有一本字典,如何分开所有的字符。不可分开的字符达到最少


感觉是个dp,但是似乎不是一个一维的问题。


定义solution[n],是nth字符后面加个空格,最少的不可识别字符的数目,但是万一n是属于后面出现的一坨单词里面的呢?。。有点复杂


这题还是要从最基础的做法开始。。。


但是实在没看懂,似乎对我而言,就是从序列里面挨个匹配,固定前1到n个字符为整体,做检查,加上剩下的部分再来一遍。


但是书上的做法似乎是反过来的。





 







你可能感兴趣的:(CCI 复习笔记 17)