题源: 24. 两两交换链表中的节点
方法:迭代
这个解法采用迭代方法,通过更新链表的指针来交换相邻的节点。使用了一个哑节点(dummy node)来简化边界条件,特别是链表头部的处理。
解题步骤
- 初始化哑节点:创建一个新的哑节点
dummyHead
并将其next
指针指向head
,这样可以避免处理头节点的特殊情况。 - 迭代交换:遍历链表,检查当前节点的后两个节点是否存在。
- 如果存在,执行以下步骤:
cur -> next = cur -> next -> next;
让cur
指向第二个节点。cur -> next -> next = tmp;
更新第二个节点的next
指向第一个节点。cur -> next -> next -> next = tmp1;
将第一个节点的next
指向第二个节点的原next
节点。
- 更新
cur
指针到下一对待交换的节点的前一个节点。
- 如果存在,执行以下步骤:
- 返回结果:由于
dummyHead
是哑节点,因此它的next
指针指向新的头节点。最后,删除哑节点并返回新的头节点。
代码分析
这个函数通过使用哑节点来避免复杂的头节点检查。这是一个常见的技巧,因为它可以减少特殊情况的检查,使代码更加简洁。同时,这个函数还精心管理了节点间的指针关系,确保了节点交换的正确性,并在结束时释放了哑节点以避免内存泄露。
复杂度分析
- 时间复杂度:O(n),其中 n 是链表中的节点数量。这是因为我们需要遍历链表中的每个节点。
- 空间复杂度:O(1),我们只使用了常数级别的额外空间。
Code
/**
* 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(0);
dummyHead -> next = head;
ListNode * cur = dummyHead;
while(cur -> next != NULL && cur -> next -> next != NULL){
ListNode *tmp = cur -> next;
ListNode *tmp1 = cur -> next -> next -> next;
cur -> next = cur -> next -> next; //1
cur -> next -> next = tmp; //2
cur -> next -> next -> next = tmp1; //3
cur = cur -> next -> next;
}
ListNode *res = dummyHead -> next;
delete dummyHead;
return res;
}
};