24. 两两交换链表中的节点(力扣LeetCode)
24. 两两交换链表中的节点
题目描述
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
提示:
- 链表中节点的数目在范围 [0, 100] 内
- 0 <= Node.val <= 100
解题思路
- 在交换两个相邻节点时,需要找到两个相邻节点的前一个结点,才能进行交换
对于头节点与其相邻的节点,我们只需要使用虚拟头节点就可以交换
只使用一个临时节点
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyhead=new ListNode(0);
dummyhead->next=head;
ListNode* cur=dummyhead;
//当节点为偶数时,cur->next指向空指针停止
//当节点为奇数时,cur->next->next为空指针时停止
//cur->next!=nullptr要放在cur->next->next!=nullptr前面,不然会导致空指针异常
//当节点为偶数时,原本cur->next已经指向空指针,cur->next->next!=nullptr放在前面会先判断,从而导致空指针异常
while(cur->next!=nullptr&&cur->next->next!=nullptr)
{
ListNode* tmp=cur->next;//步骤一:保存1
cur->next=cur->next->next;//步骤二:cur->2
tmp->next=cur->next->next;//步骤三:1->3;
cur->next->next=tmp;//步骤四:2->3
cur=cur->next->next;// cur移动两位,准备下一轮交换
}
return dummyhead->next;
}
};
错误代码
这是我写的一个错误代码,原因是没弄懂tmp临时节点,我以为先将tmp指向节点3,然后再将cur指向2,节点2再指向1,就可以连起来,但是操作了临时节点就相当于操作了临时节点保存的节点1(因为二者地址相等),从而导致丢失了节点2的地址。
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;//保存1
tmp->next=cur->next->next->next;//1->3
cur->next=cur->next->next;//cur->2
cur->next->next=tmp;//2->1
cur=cur->next->next;
}
return dummyhead->next;
}
};
使用两个临时节点
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* tmp1=cur->next;//保存1
ListNode* tmp2=cur->next->next->next;//保存3
cur->next=cur->next->next;//步骤一:cur->2
cur->next->next=tmp1;//步骤二:2->1
tmp1->next=tmp2;//步骤三:1(tmp1)->3
// cur移动两位,准备下一轮交换
cur=cur->next->next;
}
// 返回链表的新头节点,即虚拟头节点的下一个节点
ListNode* newhead=dummyhead->next;
delete dummyhead; // 删除虚拟头节点以防止内存泄漏
return newhead;
}
};