反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
1 2
| 输入: 1->2->3->4->5->NULL, m = 2, n = 4 输出: 1->4->3->2->5->NULL
|
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
以前写过206. 反转链表的题解,本题是该题的升级版,总的来说还是递归的思想。206. 反转链表通过递归,使得head的下个元素的next(即head.next.next)指针指向head,然后断开head的next指针,其实就实现了一个元素的反转,最终头结点指向反转后最后一个结点。
我们思考,如果反转前N个元素应该怎么做,首先肯定需要一个记录终止点的元素,要不然就跟反转整个链表一样。这里可以设置一个ListNode用来标记后继不需要反转的链表的头结点,因为我们反转后head结点指向该链最后一个元素,只要让head.next接上后继链表即可。具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ListNode successor = null; private ListNode reverseN(ListNode head, int n) { if (n == 1) { successor = head.next; return head; } ListNode last = reverseN(head.next, n - 1); head.next.next = head; head.next = successor; return last; }
|
对于反转指定区间的元素,我们可以将一般特殊化,其实也是一种变种的反转前N个结点的操作,将head作为第一个元素时,我们反转区间从m开始,如果将head.next作为第一个元素时,反转区间将从m – 1开始,那么总有一个结点,使得我们的m == 1,这时我们套用反转前N个结点的方式进行操作即可。
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
class Solution { public ListNode reverseBetween(ListNode head, int m, int n) { if (m == 1) return reverseN(head, n); head.next = reverseBetween(head.next, m - 1, n - 1); return head; }
ListNode successor = null; private ListNode reverseN(ListNode head, int n) { if (n == 1) { successor = head.next; return head; } ListNode last = reverseN(head.next, n - 1); head.next.next = head; head.next = successor; return last; } }
|