(一)相交链表
相交链表
思路:先分别计算出A列表和B列表的长度,判断它们的尾节点是否相等,如果不相等就不相交,直接返回空。然后让两个列表中的长的列表先走它们的差距步,然后再一起走,第一次相等的点就为交点。 注意要用地址判断是否相交。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *curA = headA, *curB = headB;
int lenA = 1, lenB = 1;
//计算链表长度
while(curA->next)
{
curA = curA->next;
++lenA;
}
while(curB->next)
{
curB = curB->next;
++lenB;
}
//判断尾节点是否相交,不相交就不相交
if(curA != curB)
{
return NULL;
}
//长的先走差距步
//假设A列表较长
int gap = abs(lenA - lenB);
struct ListNode *longlist = headA, *shortlist = headB;
if(lenB > lenA)
{
longlist = headB;
shortlist = headA;
}
while(gap--)
{
longlist = longlist->next;
}
while(longlist != shortlist)
{
longlist = longlist->next;
shortlist = shortlist->next;
}
return shortlist;
}
(二)环形链表(一)
环形链表
链表的最后一个节点的下一个指针指向链表中的某个非空节点,形成一个闭环,叫环形链表。
如何判断一个链表是否有环:
1、创建一个快指针,一个慢指针指向链表的头节点head
2、让快指针一次向后移动两个节点,慢指针一次向后移动一个节点。
struct ListNode* slow = head,*fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
return true;
}
return false;
为什么循环结束条件是fast && fast->fast
当链表中有环时,fast和fast->next永远不会指向NULL;
当链表中无环时,①fast移动两次后,刚好指向NULL,结束循环;②fast移动一次后就已经指向NULL,在进行移动,就是对NULL的解引用
(三)环形链表 二
环形链表 II
题目的意思是说:判断链表是否有环,有环则返回入环点,没有则返回NULL。
假设链表从头到入环点的距离为a,环的大小为c,slow和fast相遇时slow走的距离为b,那么有下面的式子:
所以,记录一个指针ptr指向链表头部,一个指针meet指向slow和fast相遇的位置,让prt和meet一起走,它们两个相遇就是入环点。
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow = head,*fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
struct ListNode* meet = slow;
struct ListNode* ptr = head;
while(meet != ptr)
{
meet = meet->next;
ptr = ptr->next;
}
return meet;
}
}
return NULL;
}