• LeetCode 算法:两两交换链表中的节点 c++


    原题链接🔗两两交换链表中的节点
    难度:中等⭐️⭐️

    题目

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

    示例 1
    在这里插入图片描述

    输入:head = [1,2,3,4]
    输出:[2,1,4,3]

    示例 2

    输入:head = []
    输出:[]

    示例 3
    输入:head = [1]
    输出:[1]

    提示

    • 链表中节点的数目在范围 [0, 100] 内
    • 0 <= Node.val <= 100

    题解

    迭代法【双指针迭代法】

    1. 题解

    "两两交换链表中的节点"是一个常见的链表问题,它主要考察对链表操作的理解和双指针技巧的应用。下面是解决这个问题的一般思路:

    1. 理解问题:首先明确题目要求,即给定一个链表,需要将链表中的节点两两交换,如果链表长度为奇数,最后一个节点保持不变。

    2. 虚拟头节点:为了简化操作,特别是处理原链表头节点的交换,可以创建一个虚拟头节点(dummy node),它的next指向原链表的头节点。这样,我们可以统一处理所有情况,包括链表只有一个节点或为空的情况。

    3. 使用双指针:定义两个指针currentprevcurrent用于遍历链表,prev用于指向当前current节点的前一个节点。初始时,prev指向虚拟头节点。

    4. 遍历链表:遍历链表,每次循环处理一对节点。在每次循环中:

      • 检查currentcurrent->next是否非空,确保有一对节点可以交换。
      • 交换currentcurrent->next的节点。可以通过改变指针的指向来实现节点的交换,而不需要移动节点的数据。
    5. 交换节点:交换节点的步骤如下:

      • 保存current->next的下一个节点,即second
      • secondnext指向current
      • current->next指向second
      • 更新prevnext指向second,即交换后的第二个节点。
    6. 更新指针:交换完成后,更新prev为当前的currentcurrent向前移动两位,即移动到下一对节点。

    7. 处理特殊情况:如果链表长度为奇数,循环结束后,current将指向最后一个节点,此时不需要交换,直接结束循环。

    8. 返回结果:最后,返回虚拟头节点的下一个节点,即交换后链表的新头节点。

    9. 释放资源:如果有必要,释放所有动态分配的节点,以避免内存泄漏。

    这个算法的时间复杂度是O(n),其中n是链表的长度,因为我们只遍历了链表一次。空间复杂度是O(1),因为我们只使用了有限的额外空间。

    1. 复杂度: 时间复杂度O(n),其中n是节点数,空间复杂度O(1)。
    2. 代码过程:如demo所示。
    3. c++ demo
    #include 
    
    // 定义链表节点结构体
    struct ListNode {
        int val;
        ListNode* next;
        ListNode(int x) : val(x), next(nullptr) {}
    };
    
    // 两两交换链表中的节点
    ListNode* swapPairs(ListNode* head) {
        // 虚拟头节点,方便处理
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        // 指向当前需要交换的节点
        ListNode* current = dummy;
    
        while (current->next && current->next->next) {
            // 交换两个节点
            ListNode* first = current->next;
            ListNode* second = current->next->next;
            first->next = second->next;
            current->next = second;
            second->next = first;
            // 移动到下一对节点
            current = first;
        }
    
        // 返回新链表的头节点
        ListNode* newHead = dummy->next;
        delete dummy; // 释放虚拟头节点
        return newHead;
    }
    
    // 打印链表的函数,用于验证结果
    void printList(ListNode* head) {
        while (head) {
            std::cout << head->val << " ";
            head = head->next;
        }
        std::cout << std::endl;
    }
    
    // 测试代码
    int main() {
        // 创建示例链表: 1->2->3->4
        ListNode* head = new ListNode(1);
        head->next = new ListNode(2);
        head->next->next = new ListNode(3);
        head->next->next->next = new ListNode(4);
    
        std::cout << "Original List: ";
        printList(head);
    
        // 调用函数交换节点
        ListNode* newHead = swapPairs(head);
    
        std::cout << "Swapped List: ";
        printList(newHead);
    
        // 释放链表内存
        while (newHead) {
            ListNode* temp = newHead;
            newHead = newHead->next;
            delete temp;
        }
    
        return 0;
    }
    
    • 输出结果:

    Original List: 1 2 3 4
    Swapped List: 2 1 4 3
    在这里插入图片描述

  • 相关阅读:
    代码随想录算法训练营第十天|二叉树完结
    全国行政区划2023年最新版
    redis(2)-hiredis-centos-ubuntu 下安装和使用
    TetheringService 启动流程
    力扣(518.377)补7.31
    pytest多进程/多线程执行测试用例
    计算机毕业设计Java家电产品售后(源码+系统+mysql数据库+lw文档)
    理解 Linux 网络命名空间
    Vue 安装与创建第一Docker的项目
    彻底理解观察者模式
  • 原文地址:https://blog.csdn.net/yanceyxin/article/details/139842355