24. 两两交换链表中的节点
笔记
插入一个虚拟头节点,后面的操作方便很多
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode *dummyHead = new ListNode(0, head);
ListNode *cur = dummyHead;
while (cur->next != nullptr && cur->next->next != nullptr) {
ListNode *tem1 = cur->next;
ListNode *tem2 = cur->next->next;
cur->next = tem2;
tem1->next = tem2->next;
tem2->next = tem1;
cur = cur->next->next;
}
return dummyHead->next;
}
};
19. 删除链表的倒数第 N 个结点
笔记
使用双指针,快指针比慢指针快n+1步,当快指针遍历到null时,慢指针遍历到需要删除的节点的前一个节点。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *dummyHead = new ListNode(0, head);
ListNode *fast = dummyHead;
ListNode *slow = dummyHead;
while (n--) {
fast = fast->next;
}
fast = fast->next;
while (fast != nullptr) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummyHead->next;
}
};
面试题 02.07. 链表相交
笔记
先遍历两个链表,记录链表的长度,若两个链表长度之差为x,则遍历长的链表x步,然后同时遍历,遇到的第一个相同的节点就是交点。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int countA = 0;
int countB = 0;
ListNode *pA = headA;
ListNode *pB = headB;
while (pA) {
pA = pA->next;
countA++;
}
while (pB) {
pB = pB->next;
countB++;
}
pA = headA;
pB = headB;
if (countA > countB) {
for (int i = 0; i < countA - countB; i++) {
pA = pA->next;
}
}
else {
for (int i = 0; i < countB - countA; i++) {
pB = pB->next;
}
}
while (pA || pB) {
if (pA == pB) return pA;
else {
pA = pA->next;
pB = pB->next;
}
}
return NULL;
}
};
142. 环形链表 II
笔记
先判断链表中有没有环,若快慢指针相交于a点,则有环。
设头节点到环的入口需要x步,从环的入口到a点需要y步,从a点到环的入口需要z步,则2*(x+y)=x+y+n(z+y),其中n表示快指针走过环的圈数,当n=1时,若从头节点和a点同时出发,则会相交于环的入口,同理n>1时。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head;
ListNode *slow = head;
bool loop = 0;
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
loop = 1;
break;
}
}
if (loop == 0) return NULL;
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return fast;
}
};