▶ 关于单链表翻转的两个问题。
▶ 206. 翻转整个单链表。
● 自己的代码,9 ms,使用了递归。
1 class Solution 2 { 3 public: 4 ListNode* reverseList(ListNode* head) 5 { 6 if (head == nullptr) 7 return nullptr; 8 ListNode *p; 9 for (p = head; p->next != nullptr; p = p->next);// 找到末元(翻转后的首元) 10 reverseNode(head); 11 return p; 12 } 13 inline void reverseNode(ListNode* p)// 翻转以 p 指向的结点为首元的单链表,并返回一个指向末元的指针(方便下一次挂上新的首元) 14 { 15 if (p == nullptr || p->next == nullptr) 16 return; 17 reverseNode(p->next); // 翻转除首元意外的部分 18 p->next->next = p; // 把首元挂到最后 19 p->next->next->next = nullptr; // 去掉成环的部分 20 return ; 21 } 22 };
● 大佬的代码,9 ms,逐格移动。
1 class Solution 2 { 3 public: 4 ListNode* reverseList(ListNode* head) 5 { 6 if (head == NULL || head->next == NULL) 7 return head; 8 ListNode *prev, *cur, *temp; 9 for(prev = NULL, cur = head; cur != NULL;) 10 { 11 temp = cur->next; 12 cur->next = prev; 13 prev = cur; 14 cur = temp; 15 } 16 return prev; 17 } 18 };
▶ 92. 要求翻转单链表中第 m 到第 n(两端包含,且 m 可以等于 n)之间的所有元。
● 自己的代码,4 ms,使用了第 206 题的结果。
1 class Solution 2 { 3 public: 4 ListNode* reverseBetween(ListNode* head, int m, int n) 5 { 6 if (head == nullptr) 7 return head; 8 ListNode newHead(-999), *lp, *rp, *lpprev, *temp; 9 newHead.next = head; 10 int i, j; 11 for (i = 1, lpprev = &newHead; i < m && lpprev != nullptr; i++, lpprev = lpprev->next);// 找到第 m-1 元和第 m 元 12 if (lpprev == nullptr || (lp = lpprev->next) == nullptr) 13 return head; 14 for (j = i, rp = lp; j < n && rp != nullptr; j++, rp = rp->next);// 找到第 n 元 15 if (rp == nullptr) 16 return head; 17 temp = rp->next; // 尾部不翻转部分的首元 18 rp->next = nullptr; // 断开翻转部分的尾部链接 19 lpprev->next = reverseList(lp);// 调用翻转函数 20 lp->next = temp; // 重新接上尾部 21 return newHead.next; 22 } 23 ListNode* reverseList(ListNode* head) 24 { 25 if (head == nullptr) 26 return nullptr; 27 ListNode *p; 28 for (p = head; p->next != nullptr; p = p->next);// 找到末元(翻转后的首元) 29 reverseNode(head); 30 return p; 31 } 32 inline void reverseNode(ListNode* p)// 翻转以 p 指向的结点为首元的单链表 33 { 34 if (p == nullptr || p->next == nullptr) 35 return; 36 reverseNode(p->next); // 翻转除首元意外的部分 37 p->next->next = p; // 把首元挂到最后 38 p->next->next->next = nullptr; // 去掉成环的部分 39 return; 40 } 41 };
● 大佬的代码,4 ms,也是使用逐格移动。
1 class Solution 2 { 3 public: 4 ListNode* reverseBetween(ListNode* head, int m, int n) 5 { 6 ListNode *first = new ListNode(0), *t_head, *first_reverse, *node; 7 first->next = head; 8 t_head = first; 9 for (int i = 0; i<m - 1; t_head = t_head->next, i++) 10 first_reverse = t_head->next; 11 node = t_head->next; 12 for (int i = m; i <= n; i++) 13 { 14 ListNode * temp = node->next; 15 node->next = t_head->next; 16 t_head->next = node; 17 node = temp; 18 } 19 first_reverse->next = node; 20 return first->next; 21 } 22 };
▶ 一个副产品,交换单链表中的两个元素。我已开始把第 92 题理解错了,以为只是交换单链表中第 m 和第 n 个元素,所以写成了下面的东西。
1 class Solution 2 { 3 public: 4 ListNode* reverseBetween(ListNode* head, int m, int n) 5 { 6 if (head == nullptr) 7 return head; 8 ListNode newHead(-999), *lp, *rp, *lpprev, *rpprev, *temp; 9 newHead.next = head; 10 int i, j; 11 for (i = 1, lpprev = &newHead; i < m && lpprev != nullptr; i++, lpprev = lpprev->next); 12 if (lpprev == nullptr || (lp = lpprev->next) == nullptr) 13 return head; 14 for (j = i, rpprev = lpprev; j < n && rpprev != nullptr; j++, rpprev = rpprev->next); 15 if (rpprev == nullptr || (rp = rpprev->next) == nullptr) 16 return head; 17 lpprev->next = rp; 18 rpprev->next = lp; 19 swap(lp->next, rp->next); 20 return newHead.next; 21 } 22 };