Problem:
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:
This is an extension problem of reverse a linked list. The first thing to do is to find the starting node of the sub-list to be reversed. Then call the reverse linked-list procedure and adjust the order of nodes. At last, link the new head with the m-1 node together to form the result linked-list. Note in the reverse procedure we connect the sub-list's last node with the n+1 node.
It's a one-pass and in place algorithm.
Code:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode *reverseBetween(ListNode *head, int m, int n) { 12 // Start typing your C/C++ solution below 13 // DO NOT write int main() function 14 if (head == NULL || head->next == NULL) 15 return head; 16 17 ListNode dmy(-1), *p, *pm; 18 dmy.next = head; 19 p = &dmy; 20 21 int cnt = 0; 22 for (; cnt < m-1; cnt++) { 23 p = p->next; 24 } 25 26 // now p points to m-1's node 27 p->next = reverse(p->next, cnt+1, n); 28 29 return dmy.next; 30 } 31 32 private: 33 ListNode *reverse(ListNode *head, int c, int n) { 34 if (head == NULL || head->next == NULL) 35 return head; 36 37 ListNode *pre, *cur, *nxt, dmy(-1); 38 dmy.next = head; 39 40 pre = 0; 41 cur = dmy.next; 42 nxt = cur->next; 43 44 while (c <= n) { 45 nxt = cur->next; 46 cur->next = pre; 47 pre = cur; 48 cur = nxt; 49 50 c++; 51 } 52 53 head->next = cur; 54 return pre; 55 } 56 };