C++:Leetcode-链表-24两两交换链表中的节点

C++:Leetcode-链表-24两两交换链表中的节点

链表联系题,加强虚拟头节点运用,加强节点交换后指针指向也随之改变的理解



题目

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。


一、思路分析

结合画图进行理解
1、创建虚拟头节点、现节点方便后续操作
2、记录第1个节点和第3个节点,方便后续交换的操作
3、进行交换,步骤一:现节点即虚拟头节点指向2节点,此时cur->next为2节点
4、步骤二:2节点指向原来的1节点,原来1节点由temp1记录,此时cur->next->next为1节点
5、步骤三:1节点指向原来的3节点,原来3节点由temp2记录,此时cur->next->next->next为1节点的指向即3节点
6、两两交换完毕,现节点向后移动两位,完成一轮交换
7、不断循环,用while判定,当两个相邻节点都不为空时进行交换

重点理解:
1、节点进行交换后,节点的指向也随之改变,别漏了这个。
2、还有返回的是交换后的头节点,但mylist中的虚拟头结点指向没有改变,还是指向最初的1,而不是交换后的2(这个不影响leetcode通过,只是影响自己输出打印)

思路流程图如下:
步骤图

二、代码

/*
Leetcode-24两两交换链表中的节点

思路:
结合画图进行理解
1、创建虚拟头节点、现节点方便后续操作
2、记录第1个节点和第3个节点,方便后续交换的操作
3、进行交换,步骤一:现节点即虚拟头节点指向2节点,此时cur->next为2节点
4、步骤二:2节点指向原来的1节点,原来1节点由temp1记录,此时cur->next->next为1节点
5、步骤三:1节点指向原来的3节点,原来3节点由temp2记录,此时cur->next->next->next为1节点的指向即3节点
6、两两交换完毕,现节点向后移动两位,完成一轮交换
7、不断循环,用while判定,当两个相邻节点都不为空时进行交换
*/

#include "iostream"
#include "vector"
#include "list"

using namespace std;

//创建节点
class ListNode
{
    
    
public:
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {
    
    }
    ListNode(int x) : val(x), next(nullptr) {
    
    }
    ListNode(int x, ListNode *l_next) : val(x), next(l_next) {
    
    }
};

//创建链表
class myLinkedList
{
    
    
public:
    int listsize;
    ListNode *dummyNode;

    myLinkedList()
    {
    
    
        listsize = 0;
        dummyNode = new ListNode(0);
    }

    ListNode *creatList(vector<int> &nums)
    {
    
    
        ListNode *current = new ListNode(nums[0]);
        dummyNode->next = current;
        for (int i = 1; i < nums.size(); i++)
        {
    
    
            current->next = new ListNode(nums[i]);
            current = current->next;
        }

        listsize += nums.size();
        return dummyNode->next;
    }

    void printList(ListNode *head)
    {
    
    
        ListNode *current = head;
        while (current != nullptr)
        {
    
    
            cout << current->val << "\t";
            current = current->next;
        }
        cout << endl;
    }
};

class Solution
{
    
    
public:
    ListNode *swapPairs(ListNode *head)
    {
    
    
        ListNode *dummyNode = new ListNode(0); //创建虚拟头节点,方便操作
        dummyNode->next = head;
        ListNode *cur = dummyNode;                                 //创建现节点,进行移动操作
        while (cur->next != nullptr && cur->next->next != nullptr) //当两个节点都不为空时,进行两两交换操作
        {
    
    
            ListNode *temp1 = cur->next;             //记录第一个节点,方便后续交换操作
            ListNode *temp2 = cur->next->next->next; //记录第三个节点,方便后续交换操作

            //开始进行交换
            //结合换图进行理解
            cur->next = cur->next->next;   //现节点即虚拟头节点指向2节点,此时cur->next为2节点,步骤1
            cur->next->next = temp1;       //2节点指向原来的1节点,原来1节点由temp1记录,此时cur->next->next为1节点,步骤2
            cur->next->next->next = temp2; //1节点指向原来的3节点,原来3节点由temp2记录,此时cur->next->next->next为1节点的指向即3节点,步骤3
            cur = cur->next->next;         //两两交换完毕,现节点向后移动两位,完成一轮交换
        }
        return dummyNode->next; //返回头节点,但mylist中的虚拟头结点指向没有改变,还是指向1,而不是交换后的2
    }
};

int main(int argc, const char **argv)
{
    
    
    myLinkedList mylist;
    vector<int> nums = {
    
    1, 2, 3, 4, 5};
    mylist.creatList(nums);
    mylist.printList(mylist.dummyNode->next);

    Solution s1;
    mylist.dummyNode->next = s1.swapPairs(mylist.dummyNode->next); //改变mylist中虚拟头节点的指向
    mylist.printList(mylist.dummyNode->next);

    return 0;
}

总结

链表的加强理解与加强运用。
参考代码随想录
https://www.programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html#%E6%80%9D%E8%B7%AF

猜你喜欢

转载自blog.csdn.net/Bellwen/article/details/128650417