1.判断一个单链表是否有环,如果单链表有环,找出环的入口节点,计算环的长度
[1]判断是否有环:
第一种方法:用两个快慢指针,一个指针一次走一步,另一个指针一次走两步,如果存在环,则这两个指针会在环内相遇。
第二种方法:遍历链表时,记录节点的地址,每次访问一个节点,查找地址集合,如果找到表示有环。可以使用map,把地址作为key,访问次数作为value。
[2]环的入口点和环的长度:
继续用上面的快慢指针方法,设起点到环的起点距离为a,环起点到两个指针的交点距离为b,环的长度为r,慢指针走了s步,则快指针走了2s步,则:
a + b = s
a + b + r = 2s
推导出r == s,a == r - b,因此在起点和交点设置两个指针,开始遍历,则必定相遇在环的起点位置,并且此时r == s,因此慢指针走的距离就是环的长度。
2.判断两个单链表是否相交
第一种方法:把两个链表遍历后,每个节点地址分别放到两个栈里面,比较栈顶的元素是否相同,如果相同表示相交。
第二种方法:把问题转换为单链表是否有环的问题,即先遍历第一个链表到尾部,然后将尾部指向第二个链表的头部,然后从第二个链表开始用两个快慢指针遍历,判断是否有环,有环则表示相交。
这里注意的是连接第二个链表后,理论应该从第一个链表头部使用快慢指针判断是否有环,但是其实不用,实际可以从链表的任意的地方开始使用快慢指针遍历判断是否有环。
3.反转单链表
第一种方法:设置一个新链表头new_head = NULL,然后把之前的链表从头遍历插入到新链表上。因为从旧链表头部遍历,并且在新链表头部插入,所以完成后便是反转。
第二种方法:设置两个指针,prev和next,prev记录节点之前的位置(因为头节点之前是NULL,所以prev初始为NULL),next记录节点之后的位置。这样遍历链表时,可以放心的摘除节点,然后重置该节点的前后指针,遍历执行便可以完成反转。
4.inline关键字
首先头文件中不但可以包含inline函数,可以包含普通函数。
inline发生在编译阶段,类似宏展开。inline只是给编译器的建议,如果函数体过于复杂,编译器也是会忽略的。
好处就是省掉了入栈和出栈操作,执行速度更快。