http://bylijinnan.iteye.com/blog/1345364
单个链表:
a.判断是否有环:快慢法(p1=p2=head,p1=p1.next,p2=p2.next.next)
b.环的第一个节点:假设p1,p2在环内的某点p相遇,则p1从p点继续遍历,p2从头节点开始遍历,两者相等的第一个点即为所求(证明略)
c.反向输出链表:利用递归。(printNode(p.next);print(p))
两个链表(均无环):
a.是否相交:各自遍历至最后一个节点,若最后一个节点相等,则相交
b.相交的第一个点:
solution1 人工构环。将B链表的表尾和A链表的表头相连,转化为求单个有环链表的第一个节点
solution2 在执行a操作时候,记录两个链表的长度len1和len2(假设len1>=len2),则p1先遍历(len1-len2)个结点,然后p2也开始遍历,两者相遇(相等)的第一个节点为所求
两个链表(均有环):
a.是否相交:将A链表的环断开,若B链表从有环变成无环,则相交
b.相交的第一个点:
solution1 将A链表的环断开,变成两个无环链表求相交的第一个点(相交的第一个点与环入口点可能不是同一个点,求环入口点就按单个有环链表求入口点一样)
solution2 找出各自的环入口,如果相等,则相交
图中包含了链表的几种情况
http://blog.youkuaiyun.com/walkinginthewind/article/details/7074022
1. 给出两个单向链表的头指针pHead1和pHead2,判断这两个链表是否相交。假设两个链表均不带环。
示意图如下:
如果两个链表相交于某一节点,那么在这个相交节点之后的所有节点都是两个链表所共有的。也就是说,如果两个链表相交,那么最后一个节点肯定是共有的。先遍历第一个链表,记住最后一个节点,然后遍历第二个链表,到最后一个节点时和第一个链表的最后一个节点做比较,如果相同,则相交,否则不相交。时间复杂度为O( len1 + len2),因为只需要一个额外指针保存最后一个节点地址,空间复杂度为O(1)。
2. 给出两个单向链表的头指针pHead1和pHead2,判断这两个链表是否相交,若相交返回第一个相交的节点。假设两个链表均不带环。
对第一个链表遍历,计算长度len1,同时保存最后一个节点的地址。
对第二个链表遍历,计算长度len2,同时检查最后一个节点是否和第一个链表的最后一个节点相同,若不相同,不相交,结束。
两个链表均从头节点开始,假设len1大于len2,那么将第一个链表先遍历len1-len2个节点,此时两个链表当前节点到第一个相交节点的距离就相等了,比较下一个节点是不是相同,如果相同就返回该节点,若不相同,两个链表都向后走一步,继续比较。
示意图如下:

3. 给出一个单向链表的头指针pHead,判断链表中是否有环。
示意图如下:

链表中有环,其实也就是自相交。我们用两个指针p1和p2从头开始遍历链表,p1每次前进一个节点,p2每次前进两个结点,若存在环,则p1和p2肯定会在环中相遇,若不存在,则p1和p2能正常到达最后一个节点(实际上是到达NULL)。
4. 给出一个单向链表的头指针pHead,判断链表中是否有环,若存在,则求出进入环中的第一个节点。
示意图如下:

红色虚线框中的节点为待求节点。
首先判断是否存在环,若不存在结束。
在环中的一个节点处断开(当然最后要记得恢复),这样就形成了两个相交的单链表,求进入环中的第一个节点也就转换成了求两个单链表相交的第一个节点。
如图所示: