24. 两两交换链表中的节点
要点
- 注意:交换两个节点的顺序需要先将
cur指向前一个节点,再通过三次修改指针,完成一对的交换 cur = cur->next->next再去对调下一对节点
O(n)写法
/**
* 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* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(-1, head);
ListNode* cur = dummyHead;
while (cur->next != nullptr && cur->next->next != nullptr) {
//由于在修改指针的过程中,会丢失指向,预先记录
ListNode* one = cur->next;
ListNode* three = cur->next->next->next;
//依次改指向
cur->next = cur->next->next;
cur->next->next = one;
one->next = three;
cur = cur->next->next;
}
return dummyHead->next;
}
};
总结
两两对调节点,按顺序操作修改指针,丢失的1号位、3号位节点就事先记录一下。
19.删除链表的倒数第N个节点
要点
- 当
fast指针指向NULL时,slow应指在待删节点的前一个,所以fast多走一步
双指针法
/**
* 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* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(-1, head);
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
while (n--) {
fast = fast->next;
}
//fast多走一步
fast = fast->next;
while (fast != nullptr) {
fast = fast->next;
slow = slow->next;
}
ListNode* tmp = slow->next;
slow->next = slow->next->next;
delete tmp;
return dummyHead->next;
}
};
总结
双指针法,也是快慢指针的一题,思路还是很朴实无华的
160. 链表相交
要点
- 将两链表右对齐后,长的链表cur指针和短的cur指针对齐,从此节点开始比对是否是同一节点
- 注意bug:没有int a, b = 0; 这种初始化方法
右对齐法
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0, lenB = 0;
while (curA != NULL) {
curA = curA->next;
lenA++;
}
while (curB != NULL) {
curB = curB->next;
lenB++;
}
if(lenA < lenB) {
int tmp = lenB;
lenB = lenA;
lenA = tmp;
curB = headA;
curA = headB;
}else{
curA = headA;
curB = headB;
}
int gap = lenA - lenB;
while (gap--) {
curA = curA->next;
}
while (curA != NULL) {
if (curA == curB) {return curA;}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
总结
就按右对齐的思路按部就班写,默认A链表为长的,要交换一下规范接下来的代码
还是要多写,写就能发现很多细小的bug
142.环形链表II
要点
fast每次走两步,slow走一步,如果有环一定相遇在环内- 相遇的话,
slow一定在第一圈环内被追上
- 由推导得,
x = z + k(z + y),当两指针分别从相遇点和head,同时一步步走,必会相遇在入圈点处(k为自然数) fast指针只要自身和fast->next非空,就不会出现空指针异常
由分析得
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
//如果有环一定相遇
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
ListNode* index1 = head;
ListNode* index2 = fast;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
}
return NULL;
}
};
总结
这题主要是x = z的关系重要,有思路代码很好写