CCI 复习笔记 3

Stack and Queue

准确来讲这两种数据结构都可以用LL来implement,所以我不是很了解为什么他们有单独存在的必要。可能仅仅是基于理论的完整性而已。不过话说回来,昨天亚马逊面试的时候我才意识到我从来没有用过STL的queue和stack,情急之下用了list.

C++里面关于queue,有两个结构,queue,以及deque,后者是“an irregular acronym of double-ended queue”,牛逼之处在于,用法和LL一样,但是可以用[]直接访问数据,而且是constant time。其他方面也没有什么特别的。

另外一个体会是,CCI这书,如果你不是java programmer,那么基本就别想太多了。还是在leetcode上练习练习代码把。比较尴尬的事情是,平时做事用的都是python,但是面试似乎还是C++比较受欢迎,也许我真的应该做一个C++的大型项目,但是实在特么没有时间。废话不说了,来吧。


3.1 如何用一个array实现三个stack


stack就是LIFO罗,没有什么特别的难度,书上给了两种设计,第一种是fixed size,用三个pointer对应三个stack的顶,初始值是-1,这个保证了可以直接递增。第二种是flexible division,代码太复杂,不过简单来讲,使用一个class来维护一个stack,这样的话似乎也不需要有什么连续性了。不然似乎每次要移动很多数据。书上的代码似乎是这么做的,shift_stack本身是recursive的,一直移动到stack.size < stack.capacity


3.2 设计一个stack, push, pop和min都是O(1)


我最初的想法比较简单,直接记录罗,然后push的时候更新罗,但是这样的话pop就歇菜了。这一类问题的共性就是,追溯的时候很麻烦。那么最蠢的办法,可不可以每次都sort一下呢?但是这样的话push和pop都不是O(1)了。不可以用sort的本质原因在于这个东西只需要min,不需要其他信息。那么可不可以用一个min-heap呢?自然也是O(log n), 这个有一个问题,就是min-heap维护heap特性的开销是log(n),但是如果这个结构可以给出min,为毛还需要heap呢?heap存在的意义是什么??

解法是这样,1.对于每一个element,记录对应的current min。2. 只记录当前的min。两者差不多,只是少了点memory要求。

想了一下刚刚的问题,heap是可以pop min,而这个记录min的问题是不一样的,原因在于,stack这里的顺序是定下来的。但是heap的意义在于,是在没有固定顺序状态下保证记录min。所以是log(n)。这题真心没有别的方法,应该


3.3 多个stack连续使用,类似于linked array的感觉


唯一需要注意的是,当stack满了以后,往前生成个新的。。。这个每次我都会想着往后生成,受到array的影响。


3.4 汉诺塔


汉诺塔没啥可说的,没见过的这辈子都不可能做出来。本质上是迭代。move n to pole2 <=> move 1:n-1 to pole1, move n to pole2, move 1:n-1 to pole2


抄点代码:

moveDisks(n-1, buffer, destination)

moveTopTo(destination)

buffer.moverDisks(n-1,destination,this)


3.5 两个Stack implement一个queue


queue是FIFO, peek和remove(pop_front)的时候,shiftStacks都要操作一遍,如果heap_new没有了,把heap_new填满,heap_old腾空,原来heap_old是 ABCDEtop, peek的时候,先把整个装进heap_new, EDCBAtop,然后就可以正常操作了。


这题的特点在于,分析哪些操作需要逆序,然后对那些操作做额外的工作。也就是说在保存的时候不做额外操作,只在提取的时候做额外操作。


3.6 对stack排序,可以额外用一个stack


这题有意思

首先学到的一个trick是,如何利用两个stack做相邻element的swap,对于顶层来说很简单,用一个temp。解决问题

然后由于可以做swap,新的stack的前两个element肯定可以in order了。下一个问题就是如何让第三个element插入这个sorted stack。这个就是把原来的element都往旧的stack上放,知道temp小于stack最上面的数字为止。

old.push(new.pop());


3.7 implement 一个结构,包含两个queue,可以dequeue其中一个,(猫或者狗),或者dequeue总体最老的


可以使用一个class,一个node带两个pointer,分别指向本种类的下一个,以及顺序上的下一个,这个很好实现。


如果用queue的话,怎么做呢?书上给的做法可能简单一些,但是其实应该差不多,用一个animal queue的class和一个animal的class,保存一个order, 也就是说猫狗都自带一个timestamp。


也就是说,我是猫狗自带多一个pointer,他是猫狗自带多一个order int。区别不大,但是他的要好些不少。



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