链表内指定区间反转
将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。
例如:
给出的链表为 1→2→3→4→5→NULL, m=2,n=4,
返回 1→4→3→2→5→NULL.
数据范围: 链表长度 0 < size ≤ 1000,0 < m ≤ n ≤ size,链表中每个节点的值满足∣val∣≤1000
要求:时间复杂度 O(n) ,空间复杂度 O(n)
进阶:时间复杂度 O(n),空间复杂度 O(1)
双指针
比较低级的写法
用容器装待反转的链表,不额外添加表头
ListNode* reverseBetween(ListNode* head, int m, int n)
{
// write code here
if (head == nullptr || m == n)
{
return head;
}
// 双指针,一个指头,一个指尾
ListNode* tempHead = head; // 开始反转的头
ListNode* tempEnd = tempHead->next;
for (int i = 0; i < m - 2; ++i)
{
tempHead = tempEnd;
tempEnd = tempEnd->next;
}
// 所有需要反转的节点装在一个容器里
vector<ListNode*> nodeList;
int ifHead = 1;
if (m == 1)
{
nodeList.push_back(tempHead);
ifHead = 0;
}
for (int i = 0; i < n - m + ifHead; ++i)
{
nodeList.push_back(tempEnd);
tempEnd = tempEnd->next;
}
// 开始反转
if (m == 1)
{
tempHead = nodeList[nodeList.size() - 1];
head = tempHead;
}
for (int i = 0; i < nodeList.size(); ++i)
{
tempHead->next = nodeList[nodeList.size() - 1 - i];
tempHead = tempHead->next;
}
tempHead->next = tempEnd;
return head;
}
另一种写法
ListNode* reverseBetween(ListNode* head, int m, int n)
{
// write code here
if (head == nullptr || m == n)
{
return head;
}
// 加个表头
ListNode* res = new ListNode(-1);
res->next = head;
// 双指针,一个指头,一个指尾
ListNode* pre = res;
ListNode* cur = head;
// 先找到m
for (int i = 0; i < m; ++i)
{
pre = cur;
cur = cur->next;
}
// 反转,交换 n - m 次
for (int i = m; i < n; ++i)
{
ListNode* temp = cur->next;
cur->next = temp->next;
temp->next = pre->next;
pre->next = temp;
}
return res->next;
}