24题主要时容易和翻转列表弄混,这题是需要虚拟头节点的,因为翻转第一对和第二对时的情况就不一样了,所以需要一个虚拟头结点,对于判断虚拟头结点的问题,看第一个和第二个的情况是否一致(自己理解)
另外是注意保存下一步所用到的节点,这个题思路简单,容易错就上面两个地方:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0);
ListNode* cur = dummyHead;
dummyHead->next = head;
while (cur->next && cur->next->next) {
ListNode* tmp = cur->next;
ListNode* tmpNext = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = tmp;
cur->next->next->next = tmpNext;
cur = cur->next->next;
}
return dummyHead->next;
}
};
19题删除倒数节点,首先考虑是删除节点那么最好还是用虚拟头结点,因为删除第一个和后面的节点情况不一样,自己先按照笨方法做了一下,fast指针先移动到最后,再计算slow指针所移动的距离:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyNode = new ListNode(0);
dummyNode->next = head;
ListNode* cur = dummyNode;
int fastIndex = 0;
while (cur) {
fastIndex++;
cur = cur->next;
}
if (n <= 0 || n >= fastIndex)
return head;
int slowIndex = fastIndex - n - 1;
cur = dummyNode;
while (slowIndex--) {
cur = cur->next;
}
cur->next = cur->next->next;
return dummyNode->next;
}
};
双指针一遍遍历的方法更高效点,注意while(fast),最后执行完的fast是末尾的空指针,slow直接落到要删除的node上,所有用while(fast->next)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
while (n--) {
fast = fast->next;
if (fast == nullptr)
return head; // 如果 n 大于链表长度,直接返回原链表
}
while (fast->next) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummyhead->next;
}
};
链表相交主要将链表对齐后再遍历,因为假设有共同的尾巴,那么从尾巴往前捋比较方便:
class Solution {
public:
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
int sizeA = 0;
int sizeB = 0;
ListNode* curA = headA;
ListNode* curB = headB;
while (curA) {
sizeA++;
curA = curA->next;
}
while (curB) {
sizeB++;
curB = curB->next;
}
int length;
if (sizeA > sizeB) {
curA = headA;
curB = headB;
length = sizeA - sizeB;
} else {
curA = headB;
curB = headA;
length = sizeB - sizeA;
}
while (length--) {
curA = curA->next;
}
while (curA) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
最后一个环形链表。我实在是不解为什么要按照数学推理来做,面试的时候哪有这个时间思考,本质就是找一个node有没有重复出现,用哈希不更好吗?用一个set或者map存储遍历过的node,如果再一次遍历到该node那就找到入口了,哈希yyds
class Solution {
public:
ListNode* detectCycle(ListNode* head) {
unordered_set<ListNode*> set;
ListNode* cur = head;
while (cur) {
if (set.find(cur) !=set.end()) {
return cur;
} else {
set.insert(cur);
}
cur = cur->next;
}
return NULL;
}
};