
必须干掉这10道,面试100%遇到!(二)
0X03环形链表
对应力扣141和力扣142,力扣141环形链表要求为:
给定一个链表,判断链表中是否有环,用O(1)内存解决。
详细分析:环形链表找入口,真的太妙了
这个问题利用快慢双指针比较高效,快指针fast每次走2步,slow每次走1步,慢指针走n步到尾时候快指针走了2n步,而环的大小一定小于等于n所以一定会相遇,如果相遇那么说明有环,如果不相遇fast先为null说明无环。
具体代码为:
力扣142是在力扣141拓展,如有有环,返回入环的那个节点,就想下图环形链表返回节点2。
这个问题是需要数学转换的,具体的分析可以看上面的详细分析,这里面提一下大题的步骤。
如果找到第一个交汇点,其中一个停止,另一个继续走,下一次交汇时候刚好走一圈,可以算出循环部分长度为y。
所以我们知道的东西有:交汇时候fast走2x步,slow走x步,环长为y。并且快指针和慢指针交汇时候,多走的步数刚好是换长y的整数倍(它两此刻在同一个位置,快指针刚好多绕整数倍圈数才能在同一个位置相聚),可以得到2x=x+ny(x=ny)。其中所以说慢指针走的x和快指针多走的x是圈长y的整数倍。
也就是说,从开头走到这个点共计x步,从这个点走x步也就是绕了几圈也回到这个点。如果说slow从起点出发,fast从这个点出发(每次走一步,相当于之前两步抵消slow走的路程),那么走x步还会到达这个点,但是这两个指针这次都是每次走一步,所以一旦slow到达循环圈内,两个指针就开始汇合了。
实现代码为:
0X04两个栈实现队列
对应剑指offer09,题意为:
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
分析:
解决这个问题,要知道栈是什么,队列是什么,两种常见数据结构格式很简单,栈的特点就是:后进先出,队列的特点就是:先进先出,栈可以想象成一堆书本,越在上面的取的越早,上面来上面出(比喻一下);队列就是想象成排队买东西,只能后面进前面出,所以两者数据结构还是有区别的,虽然都是单个入口进出,但是栈进出口相同,而队列不同。
上面描述的是一个普通栈和队列的数据结构,这里面让我们用两个栈实现一个队列的操作,这里比较容易想的方案就是其中一个栈stack1用作数据存储,插入尾时候直接插入stack1,而删除头的时候将数据先加入到另一个栈stack2中,返回并删除栈顶元素,将stack2顺序加入stack1中实现一个复原,但是这样操作插入时间复杂度为O(1),删除时间复杂度为O(n)比较高。
实现方式也给大家看下:
这样的时间复杂度是不被喜欢的,因为删除太鸡儿耗时了,每次都要折腾一番,有没有什么好的方法能够让删除也方便一点呢?
有啊,stack1可以顺序保证顺序插入,stack1数据放到stack2中可以保证顺序删除,所以用stack1作插入,stack2作删除,因为题目也没要求数据必须放到一个容器中,所以就这样组合使用,完美perfect!
具体实现的时候,插入直接插入到stack1中,如果需要删除从stack2中栈顶删除,如果stack2栈为空那么将stack1中数据全部添加进来(这样又能保证stack2中所有数据是可以顺序删除的了),下面列举几个删除的例子
其实就是将数据分成两个部分,一部分用来插入,一部分用来删除,删除的那个栈stack2空了添加所有stack1中的数据继续操作。这个操作插入删除的时间复杂度是O(1),具体实现的代码为:
文章转自公众号:bigsai
