class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* head = new ListNode(-1);
ListNode* p = head;
while(list1 && list2)
{
if(list1->val < list2->val)
{
p->next = list1;
list1 = list1->next;
}
else{
p->next = list2;
list2 = list2->next;
}
p = p->next;
}
p->next = list1 == nullptr ? list2 : list1;
return head->next;
}
};
技巧:使用优先队列,把链表节点放入一个最小堆,就可以每次获得k节点中的最小节点
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* head = new ListNode(-1);
ListNode* p = head;
while(list1 && list2)
{
if(list1->val < list2->val)
{
p->next = list1;
list1 = list1->next;
}
else{
p->next = list2;
list2 = list2->next;
}
p = p->next;
}
p->next = list1 == nullptr ? list2 : list1;
return head->next;
}
};
3、删除链表的倒数第 N 个结点(leetcode 19 中等)
技巧:使用快慢指针p1, p2,首先让p1先走k步,然后p2跟p1一起移动,直到p1走到最后一个节点,那么p2指向了倒k节点(要删除N节点,那么p2只要先走n+1步)
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* head = new ListNode(-1);
ListNode* p = head;
while(list1 && list2)
{
if(list1->val < list2->val)
{
p->next = list1;
list1 = list1->next;
}
else{
p->next = list2;
list2 = list2->next;
}
p = p->next;
}
p->next = list1 == nullptr ? list2 : list1;
return head->next;
}
};
技巧:使用快慢节点low、fast,fast每次走两步,low每次走一步,当fast走到最后一个节点,那么low就是中间节点(注意:如果链表长度是偶数,low指向的右边那个节点)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* low = head, *fast = head;
while(fast && fast->next != nullptr)
{
low = low->next;
fast = fast->next->next;
}
return low;
}
};
技巧:使用快慢指针fast、low,fast每走两步,low走一步,如果快慢指针相遇(fast==low),那么就是有环;否则如果fast变为空指针,则无环
/**
* 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) {
ListNode *low = head, *fast = head;
while(fast && fast->next != nullptr)
{
low = low->next;
fast = fast->next->next;
if(low == fast)
return true;//break; //有环
}
return false;
}
};
6、找出环形链表环的起点 II(leetcode 142 中等)
技巧:使用快慢指针fast、low,让fast每走两步,low走一步,如果快指针变成了空指针,那么无环;如果快慢指针相遇(fast == low),那么有环,此时让慢指针重新指向头结点(low=head),快慢指针一起往前走,下次相遇就是环的起点(如图解释):

如果有环,那么到达相遇点low指针走了k步,fast指针走了2k步,多走的部分在环内转圈圈(可得k步为圈大小的整数倍);假设环起点到相遇点为m步,那么相遇点到环起点就是k-m步,又因为head到环起点也是k-m步,所以快慢指针再走k-m步就会在环起点相遇
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *low = head, *fast = head;
while(fast && fast->next != nullptr)
{
low = low->next;
fast = fast->next->next;
if(low == fast)
break; //有环
}
if(fast == nullptr || fast->next == nullptr)
{
return nullptr;
}
low = head;
while(low != fast){
low = low->next;
fast = fast->next;
}
return low;
}
};
技巧1:使用hastmap记录第一链表的所有节点,让后遍历另一个链表,如果可以在hash中找到则表明他们相交
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_map<ListNode*,bool> hashmap;
ListNode* p = headA;
while(p)
{
hashmap[p] = true;
p = p->next;
}
p = headB;
while(p)
{
if(hashmap[p]){
return p;
}
p = p->next;
}
return nullptr;
}
};
进阶,技巧2:假设两个链L1,L2表相交,我们把L1独立部分长度设为len1, L2独立部分长度设为len2, 相交公共部分长度设为len3, 由于等式: len1 + len3 + len2 = len2 + len3 + len1 =>> L1长度(len1 + len3) + L2独立部分(len2) = L2长度(len2 + len3) + L1独立部分len1 ,那么只要使用两个指针p1,p2分别走完上面的路径(p1指向L1,如果遇到nullptr那么指向L2,p2指向L2,如果遇到nullptr那么指向L1),相遇的时候就是交点


/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *p1 = headA, *p2 = headB;
while(p1 != p2)
{
if(p1 == nullptr)
p1 = headB;
else
p1 = p1->next;
if(p2 == nullptr)
p2 = headA;
else
p2 = p2->next;
}
return p1;
}
};
本文介绍了多种链表操作的算法实现,包括合并两个有序链表、合并K个升序链表、删除链表倒数第N个节点、找到链表的中间节点、判断环形链表、找到环的起点以及寻找链表的相交节点。通过这些实例展示了如何利用快慢指针、优先队列等技巧解决链表问题。
&spm=1001.2101.3001.5002&articleId=123152264&d=1&t=3&u=0e2f01643afb42089b6dc95b388a8d88)
1701

被折叠的 条评论
为什么被折叠?



