Leetcode 24. 两两交换链表中的节点
初见想法:迭代法或者递归
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyhead = new ListNode(0, head);
ListNode* temp = dummyhead;
while(temp->next != nullptr && temp->next->next != nullptr)
{
ListNode* node1 = temp->next;
ListNode* node2 = temp->next->next;
node1->next = node2->next;
node2->next = node1;
temp->next = node2;
temp = node1;
}
return dummyhead->next;
}
};
迭代法,重点还是在dummyhead, 找到需要交换的两个节点的前一个节点,然后交换两个节点,再把这个结点指向以交换节点的第一个节点
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if (head == nullptr || head->next == nullptr) return head;
// 在一个swappairs中会反转两个节点,再返回新的头节点
// swappairs里面的参数是未反转两个节点里的第一个节点
ListNode* newhead = head->next;
// 新的两个节点的头节点
ListNode* temphead = swapPairs(newhead->next);
newhead->next = head;
// 连接此时已反转的节点和下一个已反转的节点
head->next = temphead;
return newhead;
}
};
递归法,基本思想如上注释,在一个swappairs里交换,然后返回以交换节点的第一个节点
Leetcode 19.删除链表的倒数第N个节点
初见想法:双指针法,见过这题
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if (head == nullptr || n < 0) return nullptr;
ListNode* dummyhead = new ListNode(0, head);
ListNode* left = dummyhead;
ListNode* right = head;
for (int i = 0; i < n; i++) right = right->next;
// 使用while loop 最好不要访问next, 无法确定这个节点是否为空节点的话
while (right)
{
left = left->next;
right = right->next;
}
left->next = left->next->next;
return dummyhead->next;
}
};
无论是增加还是删除节点,都应该设置dummyhead,这样当有且只有一个节点的时候非常方便
倒数是从1开始的
从head算,走k步,到k+1个节点,当最后right到达空节点时, 从dummyhead算走到倒数第k-1个节点,这样就可以删除倒数第k个节点了。
Leetcode 面试题 02.07. 链表相交
初见想法:直接使用hashmap记录每个节点的地址
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
// 计算两个链表的长度
ListNode *currA = headA, *currB = headB;
int lenA = 0, lenB = 0;
while (currA)
{
currA = currA->next;
lenA++;
}
while (currB)
{
currB = currB->next;
lenB++;
}
currA = headA;
currB = headB;
if (lenB > lenA)
{
swap(lenA, lenB);
swap(currA, currB);
}
int gap = lenA - lenB;
for (int i = 0; i < gap; i++) currA = currA->next;
while (currA != nullptr)
{
if (currA == currB) return currA;
currA = currA->next;
currB = currB->next;
}
return nullptr;
}
};
先让长的链表走到和短的链表一样的位置,然后再一起往后,如果存在两个节点出现一样的情况,则链表相交
Leetcode 142.环形链表II
环形链表,卡哥视频推导:here
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head, *slow = head;
while (fast != nullptr && fast->next != nullptr)
{
// 快慢节点会在环形链表中相遇
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;
}
}
// fast跑到空指针处,那么链表不是环形指针
return nullptr;
}
};
快慢指针判断是否有环,当进入环以后,快指针每次走两步,慢指针每次走一步,快指针在以每次1个节点的速度接近慢指针,也就是说,快指针一定会追上慢指针
当slow进入环时, 假设fast和slow的距离为n,fast差slown步,那么只要slow再走n步,那么slow一定被fast追上,而n是一定小于环的长度的