24. 两两交换链表中的节点 Swap Nodes in Pairs
其实没有那么复杂,我一开始没有用虚拟头来写. 但是核心部分的是没问题的.
核心部分主要搞错的就是在于转换的点和更新点.
核心代码:
ListNode* tmp = cur->next; //记录转换的点
ListNode* pre = cur->next->next->next; //记录下一对开始的点
// 1->2->3->4
cur->next = cur->next->next; //1换2
cur->next->next = tmp; //2换1
cur->next->next->next = pre; //2->3变1->3
cur = cur->next->next; //设置开头点更新为1
时间复杂度: O(n)
空间复杂度: O(1)
全部代码:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0); //设置虚拟头
dummyHead->next = head;
ListNode* cur = dummyHead;
while (cur->next != nullptr && cur->next->next != nullptr){
ListNode* tmp = cur->next; //记录转换的点
ListNode* pre = cur->next->next->next; //记录下一对开始的点
// 1->2->3->4
cur->next = cur->next->next; //1换2
cur->next->next = tmp; //2换1
cur->next->next->next = pre; //2->3变1->3
cur = cur->next->next; //设置开头点更新为1
}
return dummyHead->next;
}
};
19.删除链表的倒数第N个节点
快慢指针
快慢指针来结题, 一开始没想到, 看完解题思路一下就明白了
快指针需要先走n步,
快慢指针同时走,直到快指针的下一个节点指向NULL
但是我们现在slow指针在删除的节点上,我们不好进行删除. 所以在步骤1后面快指针需要再前进一步.
删除指针, 释放内存(c++)
时间复杂度:O(L) L代表链表长度
空间复杂度:O(1)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* DummyHead = new ListNode(0);
DummyHead->next = head;
ListNode* fast = DummyHead;
ListNode* slow = DummyHead;
//快指针先走n+1步
while (n-- && fast->next != NULL){
fast = fast->next;
}
fast = fast->next;
//快慢指针同时走
while (fast != NULL){
fast = fast->next;
slow = slow->next;
}
//删除指针,释放内存
ListNode* tmp = slow->next;
slow->next = slow->next->next;
delete tmp;
return DummyHead->next;
}
};
160.链表相交 Intersection of Two Linked List
因为两个链表的长度不一样,我们希望他们可以在相同的情况下同时进行比对.
我们把他们的尾相等,从短的链表开始进行比较.
遍历两个链表长度
判断长度, 把长的链表转换为B, 短的为A.
直到A为NULL, 如果A=B 那么返回A, 如果最后没有返回NULL;
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lA = 0, lB = 0;
while (curA){
curA = curA->next;
lA++;
}
while (curB){
curB = curB->next;
lB++;
}
curA = headA;
curB = headB;
int gap;
if (lA > lB){
swap(lA,lB);
swap(curA,curB);
}
gap = lB - lA;
while (gap--){
curB = curB->next;
}
while (curA != NULL){
if (curA == curB){
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
142.环形链表II Linked List Cycle II
其实是一个数学题. 用快慢指针来寻找链表是否有环.
快指针走两步,慢指针走一步. 快指针一定能在圈里第一圈能追上慢指针
因为在圈里快指针比慢指针快一倍,所以一定能在第一圈里找到慢指针
数学逻辑
定义链表开始到入口为x
入口到相遇为y
相遇到入口为z
slow = x+y
fast = x+y+n(y+z)
因为快指针比慢指针移动×2
数学公式如下:
所以我们再相遇处为index1, 链表头为index2
当index1等于index2时, 那么就是环形链表的入口.
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast != NULL && fast->next != NULL){
slow = slow->next;
fast = fast->next->next;
if (fast == slow){
ListNode* index1 = fast;
ListNode* index2 = head;
while (index1 != index2){
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
}
return NULL;
}
};