成对交换链表节点

本文介绍了一种在不使用额外内存的情况下,通过交换链表中相邻节点值来实现成对交换的方法。该方法只需常数空间,适用于链表数据结构的操作。

成对交换链表节点

Swap Nodes in Pairs
  • 给定一个链表,成对交换两个节点,返回新链表的头部,不允许使用额外的内存,只能在原有链表节点基础上进行操作。
  • Given a linked list, swap every two adjacent nodes and return its head.

  • For example,
    Given 1->2->3->4, you should return the list as 2->1->4->3.

  • Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

example 1

input: 1 -> 2 -> 3 -> 4

output: 2 -> 1 -> 4 -> 3

思路

  1. 可以使用两个指针,指向当前需要交换的两个节点,交换之后向链表尾部移动。
  2. 交换节点是一种方法,另外一种取巧的方法是,不交换节点,只交换节点的值

代码

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        try:
            prev = head
            tail = prev.next
            while True:
                prev.val, tail.val = tail.val, prev.val
                prev = tail.next
                tail = prev.next
        finally:
            return head

本题以及其它leetcode题目代码github地址: github地址

### C++ 实现交换链节点的位置 在 C++ 中,可以通过多种方法来实现链表节点位置的交换。以下是几种常见的实现方式及其注意事项。 #### 方法一:递归法 通过递归来实现两两交换链中的节点。这种方法的核心在于每次处理两个节点并将其余部分交给递归函数继续执行。 ```cpp class Solution { public: ListNode* swapPairs(ListNode* head) { if (head == nullptr || head->next == nullptr) { return head; } ListNode* newHead = head->next; // 新的头节点为原头节点的下一个节点 head->next = swapPairs(newHead->next); // 头节点连接到后续已交换的部分 newHead->next = head; // 原始头节点成为新头节点的下一节点 return newHead; // 返回新的头节点 } }; ``` 此方法的关键点在于边界条件的判断以及递归调用时传入参数的选择[^2]。 --- #### 方法二:迭代法(使用虚拟头节点) 为了简化逻辑复杂度,可以引入一个虚拟头节点 `dummyHead` 来统一处理各种特殊情况。这种方式能够有效减少对边界的特殊处理需求。 ```cpp class Solution { public: ListNode* swapPairs(ListNode* head) { ListNode* dummyHead = new ListNode(0); dummyHead->next = head; ListNode* current = dummyHead; while (current->next != nullptr && current->next->next != nullptr) { ListNode* firstNode = current->next; ListNode* secondNode = current->next->next; // 节点交换过程 firstNode->next = secondNode->next; current->next = secondNode; secondNode->next = firstNode; // 移动当前指针至下一对节点之前 current = firstNode; } ListNode* result = dummyHead->next; delete dummyHead; return result; } }; ``` 该方法利用了一个额外的空间存储虚拟头节点,并通过循环逐步完成每一对相邻节点的交换操作[^4]。 --- #### 方法三:迭代法(不使用虚拟头节点) 如果不希望增加额外空间开销,则可以直接基于原始链表结构进行调整。不过这种情况下需要特别注意初始状态下的头部节点变化问题。 ```cpp class Solution { public: ListNode* swapPairs(ListNode* head) { if (!head || !head->next) { return head; } ListNode* pStart = nullptr; // 存储最终结果的起始位置 ListNode* pPrefix = nullptr; // 当前被处理的一组节点之前的那个节点 ListNode* pTemp = nullptr; // 用于保存第三节点的信息 bool isFirst = true; // 是否为首对节点标志位 while (head && head->next) { pTemp = head->next->next; // 提取第三个节点 head->next->next = head; // 反转当前这一对节点的方向 if (pPrefix) { // 如果存在前置节点,则修改其指向关系 pPrefix->next = head->next; } if (isFirst) { // 更新首节点信息 pStart = head->next; isFirst = false; } head->next = pTemp; // 连接回剩余未处理部分 pPrefix = head; // 更新前置节点信息 head = head->next; // 继续向后推进 } if (isFirst) { // 若整个列长度不足两人,则无需任何改变 pStart = head; } return pStart; } }; ``` 这段代码更加注重细节控制,尤其是针对不同场景分别设置了不同的变量来进行管理[^5]。 --- ### 注意事项 无论采用哪种具体方案,在实际编码过程中都需要关注以下几个方面: - **空链表或单节点链表的情况**:这些属于极端情形,需提前做好相应检测以免程序崩溃。 - **动态内存分配与释放**:当涉及到新建对象如 `dummyHead` 时记得及时销毁它们以防泄露资源。 - **指针合法性验证**:始终确认所使用的每一个指针均处于安全范围内再尝试读写数据[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值