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.
Analysis
Java Solution
public ListNode reverseBetween(ListNode head, int m, int n) { if(m==n) return head; ListNode prev = null;//track (m-1)th node ListNode first = new ListNode(0);//first's next points to mth ListNode second = new ListNode(0);//second's next points to (n+1)th int i=0; ListNode p = head; while(p!=null){ i++; if(i==m-1){ prev = p; } if(i==m){ first.next = p; } if(i==n){ second.next = p.next; p.next = null; } p= p.next; } if(first.next == null) return head; // reverse list [m, n] ListNode p1 = first.next; ListNode p2 = p1.next; p1.next = second.next; while(p1!=null && p2!=null){ ListNode t = p2.next; p2.next = p1; p1 = p2; p2 = t; } //connect to previous part if(prev!=null) prev.next = p1; else return p1; return head; } |
Simple and best solution found in LeetCode discuss
public static ListNode reverseBetween(ListNode head, int m, int n) {
if(head == null) return null;
ListNode dummy = new ListNode(0); // create a dummy node to mark the head of this list
dummy.next = head;
ListNode pre = dummy; // make a pointer pre as a marker for the node before reversing
for(int i = 0; i pre = 1, start = 2, then = 3
// dummy-> 1 -> 2 -> 3 -> 4 -> 5
for(int i=0; i1 - 3 - 2 - 4 - 5; pre = 1, start = 2, then = 4
// second reversing: dummy->1 - 4 - 3 - 2 - 5; pre = 1, start = 2, then = 5 (finish)
return dummy.next;
}
public class ReverseLinkedListMtoN2 {
public ListNode reverseBetween(ListNode head, int m, int n) {
if (m != n) {
ListNode curr = head;
int i = 1;
ListNode prevHead = null;
ListNode tail = null;
ListNode prev = null;
ListNode next = null;
while (i < m) {
prevHead = curr;
curr = curr.next;
i++;
}
tail = curr;
next = curr.next;
while (i < n) {
prev = curr;
curr = next;
next = curr.next;
curr.next = prev;
i++;
}
if (m == 1)
head = curr;
else
prevHead.next = curr;
tail.next = next;
}
return head;
}
Why to create new ListNode???
When the same stuff can be done just by rearranging the references?
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
if(m==n)
return head;
ListNode mprev = null;
ListNode nafter = null;
ListNode mprevprev = null;
ListNode temp = head;
int i=1;
while(temp!=null && i<=n){
if(i==m-1){
mprevprev = temp;
}
if(i==m){
mprev = temp;
}
if(i==n){
nafter = temp.next;
temp.next = null;
}
++i;
temp = temp.next;
}
if(mprev.next == null)
return head;
// Reverse the link list from m to n
ListNode x = mprev;
ListNode y = x.next;
x.next = nafter;
while(x!=null && y!=null){
ListNode t = y.next;
y.next = x;
x=y;
y=t;
}
if(mprevprev!=null)
mprevprev.next =x;
else
return x;
return head;
}
}