[LeetCode85]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.
Analysis:
The idea is stright forward. There needs an safe head guard.
1 calculate the number that needs to reverse 
2 find the start position to reverse.
3. iterative reverse two node(Use two pointer)
java
public ListNode reverseBetween(ListNode head, int m, int n) {
       if(head == null || head.next == null) return head;
		ListNode newHead = new ListNode(-1);
		newHead.next = head;
		ListNode l1 = newHead;
		ListNode pre = head;
		int dis = n-m+1;
		while(m>1){
			l1 = l1.next;
			pre = pre.next;
			m--;
		}
		ListNode post = pre.next;
		while(dis>1){
			ListNode temp = post.next;
			post.next = pre;
			pre = post;
			post = temp;
			dis--;
		}
		l1.next.next = post;
		l1.next = pre;
		return newHead.next; 
    }
c++
ListNode *reverseBetween(ListNode *head, int m, int n) {
        int step = n-m;   
    ListNode* safeG = new ListNode(-1); //intro a safe guard to avoid handle head case  
            safeG->next = head;   
            head = safeG;   
            ListNode* pre = head;   
            while(m>1)   
            {   
                 pre=pre->next;   
             m--;   
            }   
            ListNode* cur = pre->next, *post = cur->next;   
            if(step>=1)   
            {   
                 while(step>0 && post!=NULL)   
                 {   
                      ListNode* temp = post->next;   
                      post->next = cur;   
                      cur = post;   
                      post = temp;   
                      step--;   
                 }   
                 ListNode* temp = pre->next;   
                  temp->next = post; 
                 pre->next = cur;   
                  
            }   
            //safeG = head;   
            head = head->next;   
            delete safeG;   
            return head; 
    }
There is another solution, not swap pointer, swap value
So the idea is to scan the linked list once, if not meet the reverse sublist, keep going, if reverse done(here the position is the middle of the sublist which needed to be reversed), return, because the latter list do not need any change. While in the sublist, for each element, (1)find the node to be swapped, (2) swap the values. In the code below, note that, (1) the stop condition is the middle of the reversed sublist (m+(n-m)/2) (2) for each element in the sublist, the swapping element is the next (n-m-(i-m)*2) element.      e.g.     1-2-3-4-5-6-7-8-9-10-null         |                        |       m=2                  n=9    for 2, just get the next (n-m) element.     1-9-3-4-5-6-7-8-2-10-null             |                |           i=3          idx=8    next element 3, the swapping element is 8.
Java
public ListNode reverseBetween(ListNode head, int m, int n) {
       if(head == null || head.next == null) return head;
		for(int i=0;i<n-m;i++){
			int n1 = m+i;
			int n2 = n-i;
			if(n1>=n2) return head;
			ListNode p1 = head;
			ListNode p2 = head;
			while(n1>1){
				p1 = p1.next;
				n1--;
			}
			while(n2>1){
				p2 = p2.next;
				n2--;
			}
			int temp = p2.val;
			p2.val = p1.val;
			p1.val = temp;
		}
		return head; 
    }

c++
ListNode *reverseBetween(ListNode *head, int m, int n) {
        ListNode* h=head;
        for (int i=0;i<n-m;i++){
            int k1=m+i;
            int k2=n-i;
            if (k1>=k2){return head;}
            ListNode* p = h;
            ListNode* q = h;
            while (k1-1>0){p=p->next;k1--;}
            while (k2-1>0){q=q->next;k2--;}
            int tmp=p->val;
            p->val=q->val;
            q->val=tmp;
        }
        return head;
    }