024.两两交换链表的节点
核心思路:若想交换相邻两个节点,必须找到要交换的第一个节点的前一个节点
难点:如何确保链表在两两交换节点后,仍然相连。所以链表的操作必须保持在统一链表上操作,而不是把链表切割再重新组装。
- Java代码实现
public ListNode swapPairs(ListNode head) {
//1.如果链表为空,或者链表仅一个元素,则不需要反转
if (head == null || head.next == null) return head;
//2.创建一个哨兵节点,方便返回
ListNode dummy = new ListNode(666,head);
ListNode prev = dummy;
//3.将链表元素进行两两反转
//分析:当链表中存在偶数个节点才可以进行反转
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语言代码实现
Node* swapPairs(Node *head){
//1.如果为空链表或只有一个节点则无需反转
if(head == NULL || head->next == NULL) return head;
//2.创建哨兵节点:用来充当头节点;用来为遍历后续节点
Node* dummy = (Node*) malloc(sizeof(Node));
dummy->next = head;
//3.创建前置节点
Node* prev = dummy;
//4.进行交换:确保为偶数个节点
while(prev->next != NULL && prev->next->next != NULL){
//创建节点
Node* first = prev->next;
Node* second = prev->next->next;
//两两交换
first->next = second->next;
second->next = first;
prev->next = second;
//重新赋值节点
prev = first;
}
return dummy->next;
}
将上述代码用递归进行重新书写,可以减少空间复杂度
- Java代码实现
public ListNode swapPairs(ListNode head) {
// base case 退出提交
if(head == null || head.next == null) return head;
// 获取当前节点的下一个节点
ListNode next = head.next;
// 进行递归
ListNode newNode = swapPairs(next.next);
// 这里进行交换
next.next = head;
head.next = newNode;
return next;
}
- C代码实现
struct ListNode* swapPairs(struct ListNode* head) {
// base case
if (head == NULL || head->next == NULL) return head;
// 获取当前节点的下一个节点
struct ListNode* next = head->next;
// 进行递归
struct ListNode* newNode = swapPairs(next->next);
// 进行交换
next->next = head;
head->next = newNode;
return next;
}