1、链表中环的入口结点

- 初始化:快指针fast指向头结点, 慢指针slow指向头结点
- 让fast一次走两步, slow一次走一步,第一次相遇在C处,停止
- 然后让fast指向头结点,slow原地不动,让后fast,slow每次走一步,当再次相遇,就是入口结点。

/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:ListNode* EntryNodeOfLoop(ListNode* pHead) {//法一:双指针ListNode *slow=pHead;ListNode *fast=pHead;while(fast && fast->next)//先快慢指针第一次相遇{slow=slow->next;fast=fast->next->next;if(slow==fast) break;}if(!fast || !fast->next) return nullptr;//无环的情况fast=pHead;//快指针回到表头while(slow!=fast)//以一样的速度再次相遇的点就是环的入口{slow=slow->next;fast=fast->next;}return fast;//法二 :hashsetunordered_set<ListNode*>st;while(pHead){if(st.find(pHead)==st.end())st.insert(pHead),pHead=pHead->next;else return pHead;}return nullptr;}};
2、判断链表中是否有环
还是双指针,快慢指针一个一次走一步,另一个一次走两步,如果相遇,则有环。(也可以unordered_set)
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/class Solution {public:bool hasCycle(ListNode *head) {if(!head) return false;ListNode *slow = head;ListNode *fast = head;while(fast && fast->next){fast = fast->next->next;slow = slow->next;if(slow == fast) return true;}return false;}};
3、合并两个排序的链表
注意,c++中申请哨兵节点可以用:new [TYPE]*
/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {if(!pHead2) return pHead1;if(!pHead1) return pHead2;ListNode *head=new ListNode(0); //申请一个哨兵节点//ListNode *head=nullptr; 段错误,混淆指针与对象,这样写是让head指向一个空指针,而不是一个节点ListNode *ptr=head;while(pHead1 && pHead2){if(pHead1->val < pHead2->val) ptr->next=pHead1,pHead1=pHead1->next;else ptr->next=pHead2,pHead2=pHead2->next;ptr=ptr->next;}while(pHead1) ptr->next=pHead1,pHead1=pHead1->next,ptr=ptr->next;while(pHead2) ptr->next=pHead2,pHead2=pHead2->next,ptr=ptr->next;return head->next;}};
4、两个链表的第一个公共结点
假如例子如下:
显然第一个公共结点为 8,但是链表 A 头结点到 8 的长度为 2,链表 B 头结点到 8 的长度为 3,显然不好办?
如果我们能够制造一种理想情况,如下:
这里先假设链表 A 头结点与结点 8 的长度 与 链表 B 头结点与结点 8 的长度相等,那么就可以用双指针。
初始化:指针 ta 指向链表 A 头结点,指针 tb 指向链表 B 头结点
如果 ta == tb, 说明找到了第一个公共的头结点,直接返回即可。
否则,ta != tb,则++ta,++tb
所以现在的问题就变成,如何让本来长度不相等的变为相等的?
假设链表 A 长度为 a, 链表 B 的长度为 b,此时 a != b
但是,a+b == b+a
因此,可以让 a+b 作为链表 A 的新长度,b+a 作为链表 B 的新长度。
如图:
/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {ListNode *p1=pHead1, *p2=pHead2;while(p1 != p2){p1 = p1 ? p1->next : pHead2;p2 = p2 ? p2->next : pHead1;}return p1;}};
题目与题解均来源于牛客网。
