①判断两个无环链表是否相交:
代码如下:
bool hasCycle(struct ListNode *head) {
struct ListNode *fast=head;
struct ListNode *slow=head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{
return true;
}
}
return false;
}
解析:
设两个指针,fast以及slow,让fast每次走两步遍历,让slow每次走一步遍历。若两指针相遇,则说明有环,若fast走到链表末尾,说明不带环。(可以想象成操场)
注意:
fast每次走3步或4步或5步,slow每次走1步,这种方法不可行。
例如:(让fast每次走三步,slow每次走一步,这种情况fast和slow永远不可能相遇)
②环形链表,求环的入口点
代码如下:
typedef struct ListNode Node;
struct ListNode *detectCycle(struct ListNode *head) {
Node* slow = head;
Node* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
//走到相遇点
if(slow == fast)
{
// 求环的入口点
Node* meet = slow;
Node* start = head;
while(meet != start)
{
meet = meet->next;
start = start->next;
}
return meet;
}
}
return NULL;
}
解解析如下:
解题思路: | |
如果链表存在环,则fast和slow会在环内相遇,定义相遇点到入口点的距离为X,定义环的长度为C,定义头到入口的距离为L,fast在slow进入环之后一圈内追上slow,则会得知: | |
slow所走的步数为:L + X | |
fast所走的步数为:L + X + N * C | |
并且fast所走的步数为slow的两倍,故: | |
2*(L + X) = L + X + N * C | |
即: L = N * C - X | |
所以从相遇点开始slow继续走,让一个指针从头开始走,相遇点即为入口节点 |
(让慢指针先走到相遇点)