```
public ListNode reverseBetween(ListNode head, int m, int n) {
if (n == m) {
return head;
}
n = n - m;
ListNode preTail = null, oldMth = head;
if (m > 1) {
for (preTail = head; m > 2; preTail = preTail.next, m--);
oldMth = preTail.next;
}
// We have the following 4 references in play
// preTail (prefix tail) - points to the (m-1)th node or null if m == 1
// oldMth - the mth node in the original list
// mth - this will become the mth node in the reordered list
// last - this will point to the (n+1)th node after re-ordering
ListNode mth = oldMth, last = mth.next;
while (n-- > 0) {
ListNode temp = last.next;
last.next = mth;
mth = last;
last = temp;
}
// Once we've reversed nodes m through n we need to
// - point preTail (or head) at the new mth node
// - point oldMth to the (n+1)th node
if (preTail != null) {
preTail.next = mth;
} else {
head = mth;
}
oldMth.next = last;
return head;
}
```