链表反转
反转全部
// 迭代
struct ListNode *reverseList(struct ListNode *head) {
struct ListNode *pre = NULL;
struct ListNode *next;
struct ListNode *cur = head;
// 原地反转
while (cur != NULL) {
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
// 递归
struct ListNode *reverseList(struct ListNode *head) {
// 递归出口
if (head == NULL || head->next == NULL) return head;
// 递归式
struct ListNode *newHead = reverseList(head->next); // 递归反转后面的链表
head->next->next = head; // 下个结点也就是反转后的尾节点,指向自己
head->next = NULL; // 自己作为新的尾节点
return newHead;
}
反转前n个
// 第n个节点的直接后继
struct ListNode *successor = nullptr;
// 反转前n个节点(递归)
struct ListNode *reverseListFront(struct ListNode *head, int n) {
if (head == nullptr || head->next == nullptr) return head;
if (n == 1) {
// 记录下原来顺序中第n+1个节点
successor = head;
return head;
}
// 反转后面n-1个节点
ListNode *newHead = reverseListFront(head->next, n ### 1);
// 添加到反转后的n-1个节点的最后面
head->next->next = head;
// 反转全部链表时,这里是null;反转前n个时,这里是原链表中第n+1个节点
head->next = successor;
return newHead;
}
反转中间
// 反转[start, end],下标从1开始
struct ListNode *reverseListMid(struct ListNode *head, int start, int end) {
// 递归出口:反转前end个
if (start == 1) return reverseListFront(head, end);
// 递归体:反转以head.next为头节点的链表
head->next = reverseListMid(head->next, start ### 1, end ### 1);
}
struct ListNode *reverseBetween(struct ListNode *head, int left, int right) {
if (head == NULL || head->next == NULL || left >= right) return head;
// 虚拟头节点
struct ListNode *dummyHead = (struct ListNode *) malloc(sizeof(struct ListNode));
dummyHead->next = head;
struct ListNode *preNode = dummyHead;
int count = left - 1;
// preNode为left的直接前驱
while (count-- > 0) preNode = preNode->next;
// 暂存反转后的子链表的尾节点
struct ListNode *newTail = preNode->next;
// 反转子链表
struct ListNode *pre = NULL, *next = NULL, *cur = preNode->next;
count = right - left + 1;
while (count-- > 0) {
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
// pre是right节点,即反转后子链表的头节点,next是原链表中right的直接后继
preNode->next = pre;
newTail->next = next;
return dummyHead->next;
}