Leetcode按题目类型总结(十六)

系统设计

Posted by Jingming on January 8, 2018

所有代码详见:https://github.com/jingminglake/Leetcode

534. Design TinyURL

题意:需要在长url和短url之间进行变换,设计两个接口,一个是long2short,另一个是short2long。

:使用两张hash表进行保存双向的映射。在处理长变短的时候,去生成,生成完之后,保存双向关系。

关于生成短的6位数字和字母相结合的url:使用一个0-9a-zA-Z的数组,然后使用随机数,从中随机取出6项组成tinyUrl就好。另外,就是生成的tinyUrl可能之前就有了,所以要判断,有的话,那么就重新生成一个。

另外,tinyUrl只需要存最后6位,而longUrl要存全部的。

355. Design Twitter

题意:设计twitter。有四个功能:发推、获取朋友圈最新10条推文、关注、取关。

:此题难点:一是OO设计,为Twitter建立用户类、推文类。

二是如何获取朋友圈最新10条推文。方法是使用优先级队列进行一个类似于归并排序的操作:取出所有好友的推文列表,推文列表本身是按时间排好序的。首先将所有好友的第一条推文放进堆,堆大小不限,然后堆顶是最新的推文。然后,如果从堆里面往外面取,每取出一条,将该条的下一条推文存入堆,如此,一直到取到10条推文或者堆为空。

三是想不到可以使用id来作为User类的索引。id作为索引后,用户的邻居结点变成了一个int数组或集合。只需要全局的(放在Twitter类中)保存一个id到User*的map即可。

四是想不到简单的方法给tweet打上时间戳。方法就是Tweet类包含一个static变量,每new一次tweet,该staic变量就加1作为当前tweet的时间戳。

五是想不到操作各种的入口时候的边界控制,每次follow的时候,要看当前user是否存在,以及是否是follow自己,都要考虑。

六是想不到建立User的时机就是follow的时候。

353. Design Snake Game

题意:给出棋盘大小和食物一个个出现的坐标,规定贪食蛇一开始从(0, 0)出发,然后要求设计游戏,提供接口move,每次根据传入的方向更新棋局信息(分数、食物下标),返回游戏结束还是不结束。

:关键是设计数据结构。贪食蛇的走法是头每次走入一个新格子,然后把尾部删除,身子是不需要更新的。由于存在删除尾部以及加入头部的操作,因此使用deque。另外,为了快速检测是不是撞到自己身体,要把蛇的整个身体存入set。

走的时候先计算下一个位置,然后分两种情况,一种是走入自己,因为是首尾是同时移动的,所以要先要把尾部所在的格子从set中去掉,然后在检测是不是set中含有下一个加入的位置,如果有那么说明相撞,返回-1。否则考虑另外一种情况,那就是是吃食物还是走入空格子。

如果走入空格子,那么删除尾部,更新(加入)头部就好,如果是吃食物,那么就是尾部不变,之前set去掉的尾部要还原回来,然后就是加入头部,加分,食物下标加1。

271. Encode and Decode Strings

题意:设计一种encode和decode字符串数组的方法,即数组转字符串,然后字符串可以还原成数组。

:一种方法就是{数组元素长度 + 分隔符 + 数组元素}来进行encode。解码的时候,每次先定位{数组元素长度 + 分隔符 + 数组元素}的起始位置,然后根据分割符把当前元素长度切下来,然后计算出当前元素,以及下一个元素的起始位置。

379. Design Phone Directory

题意:设计电话号码生成池,可以从里面get一个未使用的号码分配给别人,然后也可以check一个号码是否已经被分配,也可以回收一个号码。

:使用队列来表示池子,使用hash表记录一个号码有没有被分配。题目给出的输入是号码的总数量maxN,所以0到maxN-1其实可以作为号码的id。

一开始把所有号码id存入queue,然后取的时候,如果队列不空,直接从queue取,然后标记该号码已使用。回收要先查看该号码是否被使用,如果没有使用,那么不操作,否则,重新加入队列,然后去除hash表里面的已使用记录。