给定两个链表LinkList1, LinkList2, 判断两个链表是否相交?
这是一道常考题了,解题的思路主要如下:
1.首先要考虑到链表是否有环?
2. 如果链表没有环,则可以分别遍历链表,如果相交,最后两个指针一定会相遇
3. 如果有环且相交, 那么环上面的任意一个节点都一定会出现在另一个链表上。那么就变成了判断
环上的点是否链表上的问题。
关于判断链表是否有环的算法:
这个算法应该在网上出现了很多次了。用两个指针同时指向链表头,一个指针的步长为1,另一个指针的步长为2,如果最后相遇,则证明有环。
否则链表无环。
为什么另一个指针的步长是2,就能一定保证在链表有环的情况下两个指针最后一定会相遇呢?有没有可能最后两个指针不相遇呢?
分析一下:
假设链表是有环的,我们称步长为2的指针为快指针(p_fast), 步长为1的指针为慢指针(p_slow).
p_fast一定会先进入环,p_slow后进入环。假设当p_slow进入环时,p_fast到p_slow这间超出的节点个数为K. (p_fast有可能已经在环内转了几圈)
如果N步之后, p_fast经过了2*N个节点, p_slow经过了N个节点
要使它们能相遇:
2*N = N + K
N = K
K为整数,N可以满足。所以一定会相遇。
如果p_fast的步长为3呢?
3*N = N + K
2*N = K
N = K/2
此时如果K是奇数,那么p_fast和p_slow就永远没有相遇的一天了。
所以快指针的步长为2不是随意定的。
#include <time.h> #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct _node_t{ int val; _node_t *next; }node_t; int check_loop(node_t *link_head, node_t **cross_node) { node_t *p_fast; node_t *p_slow; int has_loop; p_fast = link_head; p_slow = link_head; has_loop = 0; while (p_fast != NULL && p_slow != NULL) { p_slow = p_slow->next; if (p_fast->next != NULL){ p_fast = p_fast->next->next; } else { break; } if (p_slow == p_fast){ has_loop = 1; *cross_node = p_slow; break; } } return has_loop; } int check_node_exist(node_t *link_head, node_t *node) { node_t *p = link_head; int ret = 0; while (p) { if (p == node){ ret = 1; break; } p = p->next; } return ret; } int link_cross(node_t *link_head1, node_t *link_head2) { int flag1, flag2; int ret; node_t *node; flag1 = check_loop(link_head1, &node); flag2 = check_loop(link_head2, &node); ret = 0; /* Neigher of the two link_list has loop */ if (flag1 == 0 && flag2 == 0) { node_t *p1 = link_head1; node_t *p2 = link_head2; while (1) { if (p1 == p2){ /* crossed */ ret = 1; break; } if (p1->next){ p1 = p1->next; } if (p2->next){ p2 = p2->next; } if (p1->next == NULL && p2->next == NULL){ /* both link_list come to the end */ ret = 0; break; } } } else if (flag1 == 1){ /* find out one node in the loop and check its existence in the other link_list*/ ret = check_node_exist(link_head2, node); } else{ /* find out one node in the loop and check its existence in the other link_list*/ ret = check_node_exist(link_head1, node); } return ret; }