描述
将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。
例如:
给出的链表为 1\to 2 \to 3 \to 4 \to 5 \to NULL1→2→3→4→5→NULL, m=2,n=4m=2,n=4,
返回 1\to 4\to 3\to 2\to 5\to NULL1→4→3→2→5→NULL.
数据范围: 链表长度 0 < size \le 10000<size≤1000,0 < m \le n \le size0<m≤n≤size,链表中每个节点的值满足 |val| \le 1000∣val∣≤1000
要求:时间复杂度 O(n)O(n) ,空间复杂度 O(n)O(n)
进阶:时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)
示例1
输入:{1,2,3,4,5},2,4
返回值:{1,4,3,2,5}
示例2
输入:{5},1,1
返回值:{5}
思路:
1、首先定义一个反转链表函数
void reverse(ListNode* head)
{
ListNode* pre= NULL;
ListNode* cur = head;
while(cur)
{
ListNode* temp = cur->next;
cur->next = pre;
pre= cur;
cur= temp;
}
}
2、定义一个头节点,因为头节点有可能发送变化
ListNode *dummyNode = new ListNode(-1);
dummyNode->next = head;
3、找到给定区间
ListNode *pre = dummyNode;
// 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
// 建议写在 for 循环里,语义清晰
for (int i = 0; i < left - 1; i++) {
pre = pre->next;
}
// 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
ListNode *rightNode = pre;
for (int i = 0; i < right - left + 1; i++) {
rightNode = rightNode->next;
}
4、将给定范围截取出来
// 第 3 步:切断出一个子链表(截取链表)
ListNode *leftNode = pre->next;
ListNode *curr = rightNode->next;
// 注意:切断链接
pre->next = nullptr;
rightNode->next = nullptr;
5、反转截出的链表
reverse(leftNode);
6、将链表进行重新连接
pre->next = rightNode;
leftNode->next = cur1;
完整
#include<iostream>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
ListNode(int x=0):val(x),next(NULL){}
};
ListNode* createList()
{
int a = 0;
ListNode* dummy = new ListNode();
ListNode* tail = dummy;
ListNode* temp = NULL;
while (true)
{
cin >> a;
temp = new ListNode(a);
tail->next = temp;
tail = tail->next;
if (cin.get() == '\n')
break;
}
return dummy->next;
}
void printList(ListNode* head)
{
ListNode* out = head;
while (out != NULL)
{
cout << out->val << ',';
out = out->next;
}
cout << endl;
}
//采用遍历方式进行反转
void reverseList(ListNode* head)
{
ListNode* pre = NULL;
ListNode* cur = head;
while (cur != NULL)
{
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
//return pre;
}
ListNode* reverseBetween(ListNode* head, int m, int n)
{
ListNode* pre = new ListNode();
ListNode* cur = head;
pre->next = cur;
//第1步 找到左边界点(m前一个节点)
for (int i = 1; i < m; i++)
{
pre = pre->next;
cur = cur->next;
}
ListNode* rightNode = cur;
//第二步,找到右边界点(n)
for (int i = m; i < n; i++)
{
rightNode = rightNode->next;
}
//第三步截取链表
ListNode* leftNode = pre->next;
ListNode* post = rightNode->next;
pre->next = NULL;
rightNode->next = NULL;
//第四步反转截取的链表
reverseList(leftNode);
//重新拼接链表
pre->next = rightNode;
leftNode->next = post;
return head;
}
int main()
{
int m = 0, n = 0;
while (true)
{
ListNode* head = createList();
cin >> m >> n;
ListNode* result = reverseBetween(head,m,n);
printList(result);
}
return 0;
}