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;
    }
};