1、解题思路
- 定位反转区间:首先找到第 m-1 个节点(即反转区间的前一个节点),记为 pre。然后定位到第 m 个节点,记为 start,这是反转区间的第一个节点。定位到第 n 个节点,记为 end,这是反转区间的最后一个节点。记录 end 的下一个节点 next,以便反转后连接剩余链表。
- 反转区间:将 start 到 end 之间的节点进行反转。反转后,start 将成为反转区间的最后一个节点,end 将成为反转区间的第一个节点。
- 重新连接链表:将 pre 的 next 指向 end(反转后的第一个节点)。将 start 的 next 指向 next(反转区间后的第一个节点)。
- 特殊情况处理:如果 m == 1,即从链表头开始反转,此时 pre 为 nullptr,需要特殊处理。
2、代码实现
C++
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
if (head == nullptr || m == n) {
return head;
}
ListNode dummy(0), *pre = &dummy;
dummy.next = head;
// 移动到第 m-1 个节点
for (int i = 1; i < m; ++i) {
pre = pre->next;
}
ListNode* start = pre->next; // 第 m 个节点, 反转区间的第一个节点
ListNode* end = start; // 第 n 个节点, 反转区间的最后一个节点
// 移动到第 n 个节点
for (int i = m; i < n; ++i) {
end = end->next;
}
ListNode* next = end->next; // 第 n+1 个节点
end->next = nullptr; // 切断反转区间
// 反转区间
ListNode* prev = nullptr;
ListNode* cur = start;
while (cur != nullptr) {
ListNode* tmp = cur->next;
cur->next = prev;
prev = cur;
cur = tmp;
}
// 重新连接链表
pre->next = end; // pre 指向反转后的头节点 (原 end)
start->next = next; //反转后的尾节点 (原 start) 指向 next
return dummy.next;
}
};
Java
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here
if (head == null || m == n) {
return head;
}
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
// 移动到第 m-1 个节点
for (int i = 1; i < m; i++) {
pre = pre.next;
}
ListNode start = pre.next; // 第 m 个节点,反转区间的第一个节点
ListNode end = start; // 第 n 个节点,反转区间的最后一个节点
// 移动到第 n 个节点
for (int i = m; i < n; i++) {
end = end.next;
}
ListNode next = end.next; // 第 n+1 个节点
end.next = null; // 切断反转区间
// 反转区间
ListNode prev = null;
ListNode curr = start;
while (curr != null) {
ListNode temp = curr.next;
curr.next = prev;
prev = curr;
curr = temp;
}
// 重新连接链表
pre.next = end; // pre 指向反转后的头节点(原 end)
start.next = next; // 反转后的尾节点(原 start)指向 next
return dummy.next;
}
}
Python
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param head ListNode类
# @param m int整型
# @param n int整型
# @return ListNode类
#
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
# write code here
if not head or m == n:
return head
dummy = ListNode(0)
dummy.next = head
pre = dummy
# 移动到第 m-1 个节点
for _ in range(1, m):
pre = pre.next
start = pre.next # 第 m 个节点,反转区间的第一个节点
end = start # 第 n 个节点,反转区间的最后一个节点
# 移动到第 n 个节点
for _ in range(m, n):
end = end.next
next_node = end.next # 第 n+1 个节点
end.next = None # 切断反转区间
# 反转区间
prev = None
curr = start
while curr:
temp = curr.next
curr.next = prev
prev = curr
curr = temp
# 重新连接链表
pre.next = end # pre 指向反转后的头节点(原 end)
start.next = next_node # 反转后的尾节点(原 start)指向 next_node
return dummy.next
3、复杂度分析
- 时间复杂度:O(n),最多遍历链表两次。
- 空间复杂度:O(1),仅使用固定数量的额外指针。