链表 - 24. 两两交换链表中的节点(C#和C实现)
题目描述
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
示例:
输入:1->2->3->4
输出:2->1->4->3
解题思路
使用迭代或递归的方式来实现两两交换链表中的节点。
解题步骤
迭代方法:
- 初始化一个虚拟头节点
dummy
,使其next
指向链表的头节点。 - 初始化指针
prev
,初始指向虚拟头节点。 - 使用循环遍历链表,每次交换两个节点,更新
prev
的next
指针,直到遍历完整个链表。
递归方法:
- 使用递归实现两两交换链表中的节点,递归的终止条件是当前节点为
null
或者next
节点为null
。 - 在递归过程中,交换当前节点和下一个节点,并递归调用下下个节点。
- 返回新的头节点。
C#代码实现(迭代方法)
public ListNode SwapPairs(ListNode head) {
// 创建一个虚拟节点,指向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;
// 将第一个节点的指针指向第二个节点的指针指向的节点
first.next = second.next;
// 将第二个节点的指针指向第一个节点
second.next = first;
// 将前一个节点的指针指向第二个节点
prev.next = second;
// 将前一个节点指向第一个节点
prev = first;
}
// 返回虚拟节点的下一个节点
return dummy.next;
}
C代码实现(迭代方法)
struct ListNode* swapPairs(struct ListNode* head) {
// 创建一个虚拟头节点
struct ListNode* dummy = malloc(sizeof(struct ListNode));
dummy->next = head;
// 创建一个前一个节点
struct ListNode* prev = dummy;
// 当前一个节点下一个节点不为空,且下下个节点不为空时,进行交换
while (prev->next != NULL && prev->next->next != NULL) {
// 创建两个节点,分别指向前一个节点下一个节点和下下个节点
struct ListNode* first = prev->next;
struct ListNode* second = prev->next->next;
// 将第一个节点指向下下个节点
first->next = second->next;
// 将第二个节点指向第一个节点
second->next = first;
// 将前一个节点指向第二个节点
prev->next = second;
// 将前一个节点指向第一个节点
prev = first;
}
// 返回虚拟头节点的下一个节点
return dummy->next;
}
C#代码实现(递归方法)
public ListNode SwapPairs(ListNode head) {
// 如果链表为空或者只有一个节点,则直接返回
if (head == null || head.next == null) {
return head;
}
// 定义一个新的头节点,用来保存交换后的链表
ListNode newHead = head.next;
// 将头节点的下一个节点作为头节点,进行递归调用
head.next = SwapPairs(head.next.next);
// 将新的头节点的下一个节点指向头节点
newHead.next = head;
// 返回新的头节点
return newHead;
}
C代码实现(递归方法)
struct ListNode* swapPairs(struct ListNode* head) {
// 如果链表为空或者只有一个节点,直接返回
if (head == NULL || head->next == NULL) {
return head;
}
// 保存第二个节点
struct ListNode* newHead = head->next;
// 将head的next指向下一个节点的next,即指向第二个节点
head->next = swapPairs(head->next->next);
// 将第二个节点的next指向head,即指向第一个节点
newHead->next = head;
return newHead;
}
时间复杂度和空间复杂度
- 时间复杂度:O(n),其中 n 是链表的长度。每个节点最多被访问一次。
- 空间复杂度:O(1)。除了常数级别的变量,算法的空间复杂度是常数级别的。
参与点评
读者朋友们,如果您在阅读过程中,对文章的质量、易理解性有任何建议,欢迎在评论区指出,我会认真改进。