Reverse a linked list II

LeetCode problem 92. Reverse Linked List II.

## Problem description

Reverse a linked list from position *m* to *n*. **Do it in one-pass.**

Note
1 ≤ *m* ≤ *n* ≤ length of list.
Example
* Input: 1 → 2 → 3 → 4 → 5 → NULL, m = 2, n = 4
* Output: 1 → 4 → 3 → 2 → 5 → NULL

## Analysis

The assumption in this problem is that 1 ≤ *m* ≤ *n* ≤ length of list, which means that *m* and *n* are always valid indices, and that we are reversing the linked list on the *closed* interval [*m*, *n*].

Also note that in this problem the head node has index 1, instead of 0 from the sense of arrays.

So we can do the following:

1. Break the node into three segments: "1 through m-1", "m through n", "and n+1 through end".
	* If m = 1, then the first segment does not exist. Otherwise, we need to record the tail of the first segment.
	* If n = length of linked list, then the third segment does not exist. Otherwise, we need to record the head of the third segment.
	* Since we only do the problem in **one-pass**, we do not obtain the head of the third segment in advance. Instead, we will reach that head when we have finished reversing the second segment.
2. Reverse the second segment.
	* The original tail of this segment has its `next` pointer pointing to the head of the third segment. The value will be `nullptr` if the third segment does not exist. So we can record the head of the third segment.
	* After reversing the second segment, the original head of the second segment automatically becomes the tail, with its `next` pointer updated to be `nullptr`. The original tail of this segment becomes the new head.
	* We need to record the new head of the second segment.
3. Join the tail of the first segment (if it exists) with the new head of the second segment.
	* If the first segment does not exist, then we just return the new head of the second segment.
4. Join the tail of the second segment (the original head of this segment) with the head of the third segment (if it exists).
	* If this segment does not exist, then the original head of the second segment will have its next pointer point to `nullptr`. In this case nothing is done for this step.

### Complexity analysis

Time complexity
The time complexity is **O(n)**, where *n* is the upper bound index of the interval to reverse.
This is because once we have finished reversing the segment, we just join the reversed segment with the head of the remaining nodes. We do not need to go further beyond the reversed segment.
Space complexity
Since we did not create additional data structures, the space complexity is **O(1)**.
## Solution

### C++

```
/\*\*
 \* Definition for singly-linked list.
 \* struct ListNode {
 \* int val;
 \* ListNode \*next;
 \* ListNode() : val(0), next(nullptr) {}
 \* ListNode(int x) : val(x), next(nullptr) {}
 \* ListNode(int x, ListNode \*next) : val(x), next(next) {}
 \* };
 \*/
class Solution {
public:
 ListNode\* reverseBetween(ListNode\* head, const int& m, const int& n) {
 if ((head == nullptr) || (head->next == nullptr)) {
 return head;
 }

 // get tail of first segment
 // and the head of second segment (the head of the list to reverse)
 int i = 1;
 ListNode \*curr = head;
 for (; i < m - 1; ++i) {
 // write m-1 because we want curr
 // to land at the tail of first segment
 curr = curr->next;
 }
 ListNode \*firstTail = (m <= 1) ? nullptr : curr;
 ListNode \*secondHead = (m <= 1) ? curr : curr->next;
 curr = secondHead;

 // reverse second segment
 ListNode \*prev = nullptr;
 for (i = m; i <= n; ++i) {
 ListNode \*next = curr->next;
 curr->next = prev;
 prev = curr;
 curr = next;
 }
 // now secondHead is the tail of the reversed segment
 // curr points to the head of third segment
 // join them together
 secondHead->next = curr;
 // the new second head is to be joined by the first segment
 ListNode \*newSecondHead = prev;

 // join the first segment tail with the reversed second head
 if (firstTail != nullptr) {
 firstTail->next = newSecondHead;
 return head;
 }
 else {
 return newSecondHead;
 }
 }
};

```

### Java

```
/\*\*
 \* Definition for singly-linked list.
 \* public class ListNode {
 \* int val;
 \* ListNode next;
 \* ListNode() {}
 \* ListNode(int val) { this.val = val; }
 \* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 \* }
 \*/
class Solution {
 public ListNode reverseBetween(ListNode head, int m, int n) {
 if ((head == null) || (head.next == null)) {
 return head;
 }

 // get tail of first segment
 // and the head of second segment (the head of the list to reverse)
 int i = 1;
 ListNode curr = head;
 for (; i < m - 1; ++i) {
 // write m-1 because we want curr
 // to land at the tail of first segment
 curr = curr.next;
 }
 ListNode firstTail = (m <= 1) ? null : curr;
 ListNode secondHead = (m <= 1) ? curr : curr.next;
 curr = secondHead;

 // reverse second segment
 ListNode prev = null;
 for (i = m; i <= n; ++i) {
 ListNode next = curr.next;
 curr.next = prev;
 prev = curr;
 curr = next;
 }
 // now secondHead is the tail of the reversed segment
 // curr points to the head of third segment
 // join them together
 secondHead.next = curr;
 // the new second head is to be joined by the first segment
 ListNode newSecondHead = prev;

 // join the first segment tail with the reversed second head
 if (firstTail != null) {
 firstTail.next = newSecondHead;
 return head;
 }
 else {
 return newSecondHead;
 }
 }
}

```

## See also

* Reverse a linked list
* Swap nodes in pairs