24. 两两交换链表中的节点
心得
- 虚拟头指针好用,在于统一化操作,交换只要按照题意即可,但是要考虑如何保存当前的位置,此时需要引入临时变量,同时针对奇偶情况进行讨论,是否能纳入统一框架类
- 需要注意空指针报错,&&的特性,保证第一个false不会执行第二个,同时注意返回的方式
- 按照左右顺序逐个对调即可,对调前后某些结点指针发生变化无法找到之前位置,这也是提供临时变量的原因
题解
/**
* 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()
dummyHead->next = head
ListNode* cur = dummyHead
while (cur->next != nullptr && cur->next->next != nullptr){
ListNode* temp = cur->next
ListNode* temp1 = cur->next->next->next
cur->next = cur->next->next
cur->next->next = temp
cur->next->next->next = temp1
cur = cur->next->next
}
return dummyHead->next
}
}
19. 删除链表的倒数第 N 个结点
心得
- 双指针法,倒数第N个说明两个指针间隔n个,所以一次遍历的话,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(0)
dummyHead->next = head
ListNode* slow = dummyHead
ListNode* fast = dummyHead
while (n-- && fast != nullptr){
fast = fast->next
}
fast = fast->next
while (fast != nullptr){
fast = fast->next
slow = slow->next
}
ListNode* temp = slow->next
slow->next = slow->next->next
delete temp
return dummyHead->next
}
}
面试题 02.07. 链表相交
心得
题解
/**
* 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* curA = headA
ListNode* curB = headB
int m = 0
int n = 0
if (curA == nullptr || curB == nullptr) return nullptr
while (curA != nullptr){
curA = curA->next
m++
}
while (curB != nullptr){
curB = curB->next
n++
}
curA = headA
curB = headB
int delta = m > n? m-n : n - m
if (m > n){
while (delta--){
curA = curA->next
}
} else {
while (delta--){
curB = curB->next
}
}
int minVaue = m > n ? n : m
while (minVaue--){
if (curA == curB) return {
curA
}
curA = curA->next
curB = curB->next
}
return nullptr
}
}
142. 环形链表 II
心得
- 对于环的理解不足,可以类比操场跑圈,速度快慢的相遇问题,抽象出来类似解法
题解
- 双指针法,重点在于如何理解或者证明有环,快慢指针,如果无环,不可能相遇,如果有换必相遇(分别速度2和1,间隔1,相对速度1,必然相遇)
- 其次考虑索引位置,考虑特殊情况时,两者同速度
/**
* 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* fast = head
ListNode* slow = head
while (fast != nullptr&& fast->next != nullptr){
fast = fast->next->next
slow = slow->next
if (fast == slow){
ListNode* index1 = fast
ListNode* index2 = head
while (index1 != index2){
index1 = index1->next
index2 = index2->next
}
return index1
}
}
return nullptr
}
}