给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。
数据范围: n\le10000n≤10000,1<=结点值<=100001<=结点值<=10000
要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
例如,输入{1,2},{3,4,5}时,对应的环形链表如下图所示:
可以看到环的入口结点的结点值为3,所以返回结点值为3的结点。
代码:
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
if(pHead == NULL){
return NULL;
}
struct ListNode* pre = pHead, *last = pHead;
int have = 0, count = 0, i = 0;
while(pre != NULL && pre->next != NULL){
pre = pre->next->next;
last = last->next;
if(pre == last){
have = 1;
break;
}
}
if(have == 0){
return NULL;
}
do{
pre = pre->next;
count++;
}while(pre != last);
pre = last = pHead;
for(i = 0; i < count; i++){
pre = pre->next;
}
while(pre != last){
pre = pre -> next;
last = last->next;
}
return pre;
}
首先判断是否是有环的,然后找入口节点。
第一步:判断是否有环,在入口处,设置两个指针指向链表头部。第一个指针每次指向下一个,另外一个指针每次指向node->next->next,如果当走的快的那个指针能够取到NULL,说明无环,如果当两个指针再次指向同一个位置,则说明有环。
第二步:确定环中的节点数,当两个指针位置相同时,将计数器设为0。直接每次向前移动一位,当回到原处时,记录的个数就是环中的数量。
第三步:找到入口。设置两个指针,两个指针间距为环中节点数量,两个指针逐渐迭代遍历,当两个指针重合时就是入口。