局部翻转,要点是:
1 利用dummy节点
2 记录4个关键位置:
- 翻转区间前的最后一个未翻转节点 preBegin
- 翻转区间,翻转后的第一个节点 reHead
- 翻转区间,翻转后的最后一个节点 reverseEnd
- 翻转区间后的第一个未翻转节点 postEnd
3 利用3指针(reHead, preCur, cur)翻转链表
package Level4;
import Utility.ListNode;
/**
* Reverse Linked List II
*
* Reverse a linked list from position m to n. Do it in-place and in one-pass.
For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,
return 1->4->3->2->5->NULL.
Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.
*
*/
public class S92 {
public static void main(String[] args) {
int[] list = {1,2,3};
ListNode head = ListNode.create(list);
ListNode h = reverseBetween(head, 1, 2);
h.print();
}
public static ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy = new ListNode(-1); // 利用dummy节点能方便地处理头结点问题!
dummy.next = head;
ListNode preBegin = dummy; // preBegin记录翻转区间前一个元素
int cnt = 1;
while(preBegin!=null && cnt<m){ // 找到preBegin的位置
preBegin = preBegin.next;
cnt++;
}
ListNode reverseEnd = preBegin.next; // 记录翻转区间内的最后一个节点,为了和下一个没翻转区间拼起来
ListNode reHead = null; // 翻转后的头
ListNode cur = preBegin.next;
cnt = 1;
ListNode postEnd = null; // 记录在翻转区间后面的 没翻转区间的第一个节点
while(cur != null && cnt<=n-m+1){
ListNode preCur = cur;
cur = cur.next;
if(cnt == n-m+1){
postEnd = preCur.next;
}
preCur.next = reHead;
reHead = preCur;
cnt++;
}
preBegin.next = reHead;
if(reverseEnd != null){
reverseEnd.next = postEnd;
}
return dummy.next;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode beforeM = dummy;
int cnt = 1;
while(cnt < m) {
beforeM = beforeM.next;
cnt++;
}
ListNode begin = beforeM.next;
ListNode end = begin;
while(cnt < n) {
end = end.next;
cnt++;
}
ListNode afterN = end.next;
// Reverse between m to n
ListNode tmp = beforeM;
ListNode cur = begin;
while(cur != afterN) {
ListNode next = cur.next;
cur.next = tmp;
tmp = cur;
cur = next;
}
beforeM.next = end;
if(begin != null)
begin.next = afterN;
return dummy.next;
}
}