# 反轉鏈表系列問題

CSDN：反轉鏈表系列問題

## 反轉單鏈表

``````cur.next = pre;
pre = cur;
cur = tmp;
``````

``````class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
``````

``````if (cur == null || cur.next == null) {
return cur;
}
``````

``````cur.next.next = cur;
cur.next = null;
``````

``````class Solution {
public ListNode reverseList(ListNode cur) {
return reverse(cur);
}

// 反轉cur爲頭的鏈表，並把反轉後的頭節點返回
public ListNode reverse(ListNode cur) {
if (cur == null || cur.next == null) {
return cur;
}
ListNode pre = reverse(cur.next);
cur.next.next = cur;
cur.next = null;
return pre;
}
}
``````

## 反轉雙向鏈表

``````    public static DoubleNode reverseDoubleList(DoubleNode head) {
if (head == null || head.next == null) {
}
DoubleNode pre = null;
DoubleNode cur = head;
while (cur != null) {
DoubleNode tmp = cur.next;
cur.next = pre;
cur.last = tmp;
pre = cur;
cur = tmp;
}
return pre;
}

``````

## 反轉單鏈表一部分

Could you do it in one pass?

``````class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
if (head.next == null || left == right) {
// 只有一個節點，怎麼反轉都一樣
// 只要反轉一個節點，反轉前後鏈表還是一樣的
}
if (left == 1) {
// 需要換頭
ListNode pre = null;
ListNode end = head;
ListNode cur = head;
int gap = right - left + 1;
while (gap != 0) {
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
gap--;
}
end.next = cur;
return pre;
} else {
ListNode pre = null;
for (int i = 1; i < left; i++) {
pre = pre == null ? head : pre.next;
}
ListNode end = pre;
ListNode cur = pre == null ? head : pre.next;
ListNode last = cur;
int gap = right - left + 1;
while (gap != 0) {
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
gap--;
}

if (end != null) end.next = pre;
if (last != null) last.next = cur;
// 不需要換頭，返回原先的頭節點
}
}
}
``````

``````public ListNode reverseBetween(ListNode head, int left, int right)
``````

``````ListNode reverseN(ListNode head, int n)
``````

`left == 1`的條件下，主函數直接調用`reverseN(head, right)`即可。

``````    public static ListNode reverseBetween(ListNode head, int left, int right) {
if (left == 1) {
// 相當於直接反轉前 right 個元素
}
// ...
}
``````

``````head.next.next = head;
``````

``````static ListNode successor = null;
``````

`head`指向`successor`節點

``````    // 遞歸解法
public static ListNode reverseBetween(ListNode head, int left, int right) {
if (left == 1) {
}
head.next = reverseBetween(head.next, left - 1, right - 1);
}

// 反轉鏈表前N個節點
public static ListNode reverseN(ListNode head, int n) {
if (n == 1) {
}
ListNode last = reverseN(head.next, n - 1);
return last;
}

static ListNode successor = null;
``````