链表【2】

链表【2】_第1张图片

文章目录

    • 24. 两两交换链表中的节点
      • 题目
      • 算法原理
      • 代码实现
    • 143. 重排链表
      • 题目
      • 算法原理
      • 代码实现

24. 两两交换链表中的节点

题目

题目链接:24. 两两交换链表中的节点

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

示例 1:

链表【2】_第2张图片

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

示例 2:

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

示例 3:

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

提示:

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

算法原理

解法一:迭代(模拟)

做链表相关的题目,不要**吝啬空间!!!**这里我们先建立一个虚拟头节点,这样可以一视同仁第一个交换的和后面交换的。

每次交换会涉及到四个节点的修改,即要交换的2个节点和它们前后的两个节点,这里也不吝啬空间,这就创建4个临时变量。

链表【2】_第3张图片

何时终止交换:

  1. 当链表节点个数为偶数的时候,cur为空的时候停止交换
  2. 当链表节点个数为奇数的时候,next为空的时候,停止交换

解法二:递归

从宏观的角度,将递归看作一个黑盒,相信它一定能完成任务,我们的任务就是让它帮我们完成节点的两两交换

链表【2】_第4张图片

先交换后面的节点,然后把前面的节点连接起来即可。

代码实现

迭代:

/**
 * 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)
    {
        if(head == nullptr || head->next == nullptr)    return head;
        ListNode* newHead = new ListNode(0);
        newHead->next = head;
        ListNode* prev = newHead;
        ListNode* cur = prev->next;
        ListNode* next = cur->next;
        ListNode* nnext = next->next;

        while(cur && next)
        {
            //交换
            prev->next = next;
            next->next = cur;
            cur->next = nnext;
            //修改指针
            prev = cur;
            cur = nnext;
            if(cur)   next = cur->next;
            if(next)   nnext = next->next;   
        }
        prev = newHead->next;
        delete newHead;
        return prev;
    }
};

运行结果:

链表【2】_第5张图片

递归:

/**
 * 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)
    {
        if(head == nullptr || head->next == nullptr)  return head;
        auto tmp = swapPairs(head->next->next);
        auto ret = head->next;
        head->next->next = head;
        head->next = tmp;
        return ret;
    }
};

143. 重排链表

题目

题目链接:143. 重排链表

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

L0 → L1 → … → Ln - 1 → Ln

请将其重新排列后变为:

L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

链表【2】_第6张图片

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

示例 2:

链表【2】_第7张图片

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

提示:

  • 链表的长度范围为 [1, 5 * 104]
  • 1 <= node.val <= 1000

算法原理

链表的题目一般就是模拟或者递归,此题我们模拟。

这里重排可以看作找到链表的中间节点,前面部分正常排列,后面部分逆序一下,然后将两个部分一个接一个插入新链表

链表【2】_第8张图片

这样就分三步:

  1. 找到链表的中间节点(快慢指针)
    leetcode – 876.链表的中间节点
  2. 后面部分逆序
  3. 合并链表

这题的知识点很综合!!!一题抵三题

代码实现

/**
 * 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:
    void reorderList(ListNode* head)
    {
        //找中间节点
        ListNode* slow = head, *fast = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }

        //从slow->next开始逆序
        ListNode* headMid = new ListNode(0);
        ListNode* cur = slow->next;
        slow->next = nullptr;
        while(cur)
        {
            ListNode* next = cur->next;
            cur->next = headMid->next;
            headMid->next = cur;
            cur = next;
        }

        //合并链表
        ListNode* ret = new ListNode(0);
        ListNode* prev = ret;
        ListNode*cur1 = head, *cur2 = headMid->next;
        while(cur1) //cur1的长度>=cur2的长度
        {
            prev->next = cur1;
            cur1 = cur1->next;
            prev = prev->next;


            if(cur2)
            {
                prev->next = cur2;
                cur2 = cur2->next;
                prev = prev->next;
            }
        }
        delete ret;
        delete headMid;
    }
};

运行结果:

链表【2】_第9张图片

你可能感兴趣的:(原创,刷题,链表,数据结构,算法,leetcode)