题目
解答1:递归
思路
分类讨论:
- 如果链表中至少有两个节点:
原始链表的头节点变成新的链表的第二个结点
;
原始链表的第二个节点变成新的链表的头结点
;
本组第一个结点应该接上下一组的第二个结点,所以用递归找到下一组
; - 链表中没有节点,或者链表中只有一个节点:结束递归。
代码
/*
* @lc app=leetcode.cn id=24 lang=cpp
*
* [24] 两两交换链表中的节点
*/
// @lc code=start
/**
* 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;
}
//以1和2、3和4这样两两分组
//定义第二个结点作为newHead
ListNode *newHead = head->next;
//递归,完成后面组的交换
head->next = swapPairs(newHead->next);
//2后面接上1,完成第一组的交换
newHead->next = head;
return newHead;
}
};
// @lc code=end
时间复杂度和空间复杂度
- 时间复杂度: O(n) 。其中 n 是链表的节点数量。由于
成组
递归,所以最终递归次数不超过 n 2 \frac{n}{2} 2n,每次对组内两个结点进行操作,渐进时间复杂度即为 O(n) 。 - 空间复杂度:O(n) 。其中 n 是链表的节点数量。由于
成组
递归,所以最终递归次数不超过 n 2 \frac{n}{2} 2n,所需栈空间渐进时间复杂度也是 O(n) 。
解答2:迭代
思路
定义dummy,通过某一组和该组前面一个结点,对该组的两个结点进行交换。交换操作是一定需要掌握的基础,此处不再赘述。
代码
/*
* @lc app=leetcode.cn id=24 lang=cpp
*
* [24] 两两交换链表中的节点
*/
// @lc code=start
/**
* 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) {}
* };
*/
using namespace std;
class Solution
{
public:
ListNode *swapPairs(ListNode *head)
{
//定义一个头指针指向头结点
ListNode *preHead = new ListNode();
preHead->next = head;
//定义中间结点
ListNode *temp = preHead;
//还是以1和2、3和4这样两两分组
//后两个结点均不是空
while (temp->next != nullptr && temp->next->next != nullptr)
{
//p是该组第一个结点,q是该组第二个结点
ListNode *p = temp->next;
ListNode *q = temp->next->next;
//temp指向该组第二个结点
temp->next = q;
//p(第一个结点)的下一个结点应该是q的下一个结点(也就是第二组的第一个结点,不要破坏下一组的结构)
p->next = q->next;
//q(第二个结点)的下一个结点就是他前面的结点p
q->next = p;
//p(第一个结点)此时已经换成第二个结点,此时temp指向p,那么temp->next就可以指向下一组结点
temp = p;
}
//返回一开始的头结点即可
return preHead->next;
}
};
// @lc code=end
时间复杂度和空间复杂度(官方答案,说的很好)
- 时间复杂度: O(n) 。其中 n 是链表的节点数量。由于
成组
递归,所以最终递归次数不超过 n 2 \frac{n}{2} 2n,每次对组内两个结点进行操作,渐进时间复杂度即为 O(n) 。 - 空间复杂度:O(1) 。
反思与总结
递归和迭代使用的又一经典例题。