LEETCODE(力扣) 142. 环形链表 II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
提示:
链表中节点的数目范围在范围 [0, 104] 内
-105 <= Node.val <= 105
pos 的值为 -1 或者链表中的一个有效索引
自解
十分暴力的解法
用一个新链表储存所有链表的地址,依次遍历所有待查找链表的节点,将其指向的地址与新链表中储存的地址作比较。
能跑,但性能较差

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//哈希表
struct ListNode1 {
struct ListNode *address;
struct ListNode1 *next;
};
struct ListNode1 HashTable;
struct ListNode1 *tail=NULL;
struct ListNode1* find(struct ListNode *temp)
{
struct ListNode1* head=HashTable.next;
while(head!=NULL)
{
if(temp->next==head->address)return head;
head=head->next;
}
return NULL;
}
void insert(struct ListNode *temp)
{
struct ListNode1* newnode=(struct ListNode1*)malloc(sizeof(struct ListNode1));
newnode->address=temp;
newnode->next=NULL;
tail->next=newnode;
tail=tail->next;
}
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode1 *temp=NULL;
HashTable.address=NULL;
HashTable.next=NULL;
tail=&HashTable;
while(head!=NULL)
{
if((temp=find(head))!=NULL)
{
return head->next;
}
insert(head);
head=head->next;
}
return NULL;
}
力扣解
仍然是使用快慢指针
灵佬写的很清楚了
当快指针与慢指针在环中相遇时一共走了b步,设总头节点到环的头节点的节点数为a,环中的节点数为c,快指针在环中走了k圈
则2b-b=kc->b=kc(k是因为快指针一定是在节点中绕了k圈后才与慢指针相遇)
慢指针在从环节点头开始走过的距离为:b-a->kc-a(代入b=kc),也就是说此时慢指针在节点中再走a步就能到达环节点头
那我们让总节点头与慢指针同时动,两者相交时必定就在环节点的头
struct ListNode* detectCycle(struct ListNode* head) {
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (fast == slow) { // 相遇
while (slow != head) { // 再走 a 步
slow = slow->next;
head = head->next;
}
return slow;
}
}
return NULL;
}
作者:灵茶山艾府
链接:https://leetcode.cn/problems/linked-list-cycle-ii/solutions/1999271/mei-xiang-ming-bai-yi-ge-shi-pin-jiang-t-nvsq/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
仿解
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *fast=head,*slow=head;
while(fast&&fast->next)//等快慢指针相遇,若快指针遍历到NULL代表无环,会退出循环直接返回NULL
{
fast=fast->next->next;
slow=slow->next;
if(slow==fast)//相遇
{
while(head!=slow)//总头节点与慢指针同时动
{
head=head->next;
slow=slow->next;
}
return head;//相遇后退出循环,此时相遇节点即为环节点的头节点
}
}
return NULL;
}

浙公网安备 33010602011771号