Medium

题目描述

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

示例 1:

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

示例 2:

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

示例 3:

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

示例 4:

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

提示:

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

解题思路

这道题要求两两交换链表中的相邻节点。我们可以用迭代或递归的方式来解决。

方法一:迭代法(推荐)

使用虚拟头节点来简化边界情况的处理。我们维护三个指针:

  • prev:指向当前需要交换的两个节点的前一个节点
  • first:指向当前需要交换的第一个节点
  • second:指向当前需要交换的第二个节点

交换过程:

  1. prev.next 指向 second
  2. first.next 指向 second.next
  3. second.next 指向 first
  4. 更新 prev 指向 first,准备下一轮交换

方法二:递归法

递归思路更加直观:

  1. 先递归处理从第三个节点开始的子链表
  2. 交换当前的前两个节点
  3. 返回交换后的头节点

迭代法的空间复杂度更优,是首选解法。

代码实现

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode dummy(0);
        dummy.next = head;
        ListNode* prev = &dummy;
        
        while (prev->next && prev->next->next) {
            ListNode* first = prev->next;
            ListNode* second = prev->next->next;
            
            // 交换节点
            prev->next = second;
            first->next = second->next;
            second->next = first;
            
            // 移动到下一对节点
            prev = first;
        }
        
        return dummy.next;
    }
};
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        dummy = ListNode(0)
        dummy.next = head
        prev = dummy
        
        while prev.next and prev.next.next:
            first = prev.next
            second = prev.next.next
            
            # 交换节点
            prev.next = second
            first.next = second.next
            second.next = first
            
            # 移动到下一对节点
            prev = first
        
        return dummy.next
public class Solution {
    public ListNode SwapPairs(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode prev = dummy;
        
        while (prev.next != null && prev.next.next != null) {
            ListNode first = prev.next;
            ListNode second = prev.next.next;
            
            // 交换节点
            prev.next = second;
            first.next = second.next;
            second.next = first;
            
            // 移动到下一对节点
            prev = first;
        }
        
        return dummy.next;
    }
}
var swapPairs = function(head) {
    let dummy = new ListNode(0);
    dummy.next = head;
    let prev = dummy;
    
    while (prev.next && prev.next.next) {
        let first = prev.next;
        let second = prev.next.next;
        
        // 交换节点
        prev.next = second;
        first.next = second.next;
        second.next = first;
        
        // 移动到下一对节点
        prev = first;
    }
    
    return dummy.next;
};

复杂度分析

复杂度类型时间复杂度空间复杂度
迭代法O(n)O(1)
递归法O(n)O(n)

其中 n 是链表的长度。迭代法只使用常数额外空间,而递归法需要 O(n) 的递归栈空间。

相关题目