ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

链表【2】

2026/8/28 4:57:40 拓冰建站 浏览量
链表【2】

在这里插入图片描述

文章目录

    • 🥝24. 两两交换链表中的节点
      • 🥑题目
      • 🌽算法原理
      • 🥬代码实现
    • 🍎143. 重排链表
      • 🍒题目
      • 🍅算法原理
      • 🍓代码实现

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

🥑题目

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

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

示例 1:

img

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

示例 2:

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

示例 3:

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

提示:

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

🌽算法原理

解法一:迭代(模拟)

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

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

image-20231204155711189

何时终止交换:

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

解法二:递归

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

image-20231204160248300

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

🥬代码实现

迭代:

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

运行结果:

image-20231204155744401

递归:

/*** 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:

img

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

示例 2:

img

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

提示:

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

🍅算法原理

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

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

image-20231204163805607

这样就分三步:

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

运行结果:

image-20231204185049874