快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢,在使用快慢指针时可以让快指针每次沿链表向前移动2,慢指针每次向前一次。
快慢指针的应用
(一)寻找链表中心
原理:快指针的移动速度是慢指针移动速度的两倍,因此当快指针到达表尾时慢指针到达中点,但要分奇偶情况讨论。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| while(fast && slow){
if(fast->next == NULL){
return slow->data;
}
else if(fast->next != NULL&&fast->next->next == NULL){
return (slow->data + slow->next->data)/2;
}
else {
fast = fast->next->next;
slow = slow->next;
}
}
|
(二)判断单链表中是否存在环
原理:类似于在操场上跑步,快指针的速度是慢指针移动速度的两倍,让两个指针都从链表头开始遍历,如果快指针最后指向空,则说明并没有环;如果最终快慢指针相等,则说明快指针追了上慢指针存在环。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| bool JudgeCircle(LNode *head){
if(head==NULL) return false;
LNode *slow = head;
LNode *fast = head;
while(fast != NULL && fast->next->next != NULL){
slow = slow->next;
fast = fast->next->next;
if(slow == fast) return true;
}
return false;
}
|
(三)判断两个单链表是否相交
原理:首先利用快慢指针判断链表是否存在环。
(1)如果都不存在环,则如果两个单向链表有公共节点,也就是两个链表从某一节点开始,他们的p->next都指向同一个节点,每个节点只有一个p->next。因此从第一个公共节点开始,之后它们所有节点都是重合的。因此,首先两个链表各遍历一次,求出两个链表的长度L1、L2,然后可以得到它们的长度差L。然后现在长的链表上遍历L个节点,之后再同步遍历,于是在遍历中,第一个相同的节点就是第一个公共的节点。此时,若两个链表长度分别为M,N,则时间复杂度为O(M+N).
(2)如果一个存在环,另外一个不存在环,则这两个链表是不可能相交的。
(3)如果利用快慢指针发现两个链表都存在环,则判断任意一个链表上快慢指针相遇的那个节点,在不在另外一个链表上,如果在,则相交,不在,则不相交。
第一种情况实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| void Intersect(LinkList L1, LinkList L2) { if (L1 == NULL || L2 == NULL) { exit(); } LinkList p = L1; LinkList q = L2; int length1 = 0; int length2 = 0; int len = 0;
while (p->next) { length1 ++; p = p->next; } while (q->next) { length2 ++; q = q->next; }
cout<<p<<q;
cout<<length1<<length2;
if (p == q) { cout<<"相交"; if (length1 > length2) { len = length1 - length2; p = L2; q = L1; } else { len = length2 - length1; p = L1; q = L2; }
while (len) { q = q->next; len--; } while (p != q) { p = p->next; q = q->next; } cout<<p->data;
}
else { cout<<"不相交"; }
}
|
总结
上边的题是我在写LeetCode的时候发现挺有意思的就做了个汇总(当然还有一些其他的题目我想了好久,后边有时间再写),类似的题目还有寻找环的入口以及输出链表中倒数第K个节点。原理其实都差不多所以这两个题我就没有写上来。(参考来源于csdn,博客园,百度百科)