leetcode|leetcode 92. 反转链表 II

题目描述
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
相关话题:?链表???难度:?中等
说明:
1 ≤ m ≤ n ≤ 链表长度。

示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
思路:

leetcode|leetcode 92. 反转链表 II
文章图片

注:添加一个空头节点,以确保原链表的每个节点都有前驱,为了统一操作。
  • 首先定义两个指针,两个指针确定已反转的部分;begin指针指向已反转部分的前一个节点,end指针指向已反转部分的最后一个节点;例如上图,m = 2,n = 4,初始状态,节点2就是已反转的部分。
  • 然后,将end后面的节点一个一个脱离后插到begin的后面。
/** * Definition for singly-linked list. * public class ListNode { *int val; *ListNode next; *ListNode(int x) { val = x; } * } */ class Solution { public ListNode reverseBetween(ListNode head, int m, int n) { ListNode dummy = new ListNode(0); dummy.next = head; head = dummy; ListNode begin = head; ListNode end = head; //让begin指向m位置前面的节点 for(int i = 1; i < m; i++){ begin = begin.next; } end = begin.next; //end指向已反转部分的最后一个节点 for(int i = 1; i <= n - m; i++){ ListNode x = end.next; end.next = x.next; x.next = begin.next; begin.next = x; } return head.next; } }

【leetcode|leetcode 92. 反转链表 II】8个月前做这道题的思想和现在差不多,不过在coding上,8个月前没有处理好begin指针的指向(让它指向了已反转部分的第一个节点)。单向链表的前驱是很重要的,如果你想操作当前节点,比如脱离,或者在它之前插入一个节点,都需要知道它的前驱。现在的coding,beginend都是指向要插入或脱离节点的前驱,让它们指向当前节点毫无意义。
/** * Definition for singly-linked list. * public class ListNode { *int val; *ListNode next; *ListNode(int x) { val = x; } * } */ class Solution { public ListNode reverseBetween(ListNode head, int m, int n) { if(head == null||head.next == null||m == n) return head; ListNode nullHead = new ListNode(0); nullHead.next = head; head = nullHead; //begin和end指针指向已经调整的序列头尾 ListNode beforeM = head,begin = null,end = null; int count = n - m; //begin和end的初始位置决定第一个节点已调整,还需要调整n-m个节点 m = m - 1; while((m--) != 0){ beforeM = beforeM.next; //beforeM指针始终停在m位置的前一个节点 } begin = end = beforeM.next; //初始,begin和end指向m位置的元素 //将后面的节点一个一个调到前面来 while((count--) != 0){ beforeM.next = end.next; end.next = beforeM.next.next; beforeM.next.next = begin; begin = beforeM.next; } return head.next; } }

    推荐阅读