重点说三遍!!!画图画图画图
题目1:反转链表_牛客题霸_牛客网 (nowcoder.com)
要求:时间复杂度O(n) 空间复杂度O(1)
链表做题小技巧:在单链表前加上一个虚拟头节点,可以避免一些繁琐的特殊情况讨论
链表的逆置,我们可以理解为将第一个元素的后面元素依次头插到前面,就完成了逆置。如图:
从图中可以直观的发现,原本处于第一个节点位置的1号节点在不停头插过程中往后移动了,移到最后的位置,链表逆置完成。
如图,如此反复处理后续待处理的节点,直到没有待处理的元素。
代码:
class Solution {
public:
ListNode* ReverseList(ListNode* head) {
// write code here
if(head == nullptr) return nullptr;
// 虚拟头结点
ListNode* newhead = new ListNode(0);
newhead->next = head;
ListNode* cur = head->next;
ListNode* prev = head;
ListNode* next = nullptr;
while(cur)
{
// 断开原链接
prev->next = cur->next;
next = cur->next;
// 头插
cur->next = newhead->next;
newhead->next = cur;
cur = next;
}
return newhead->next;
}
};
题目2:链表内指定区间反转_牛客题霸_牛客网 (nowcoder.com)
要求:时间复杂度O(n) 空间复杂度O(1)
代码:
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
if(m == n) return head;
// 找到第m个节点
ListNode* newhead = new ListNode(0);
newhead->next = head;
int count = m;
ListNode* pprev = nullptr;
ListNode* prev = newhead;
while(count)
{
pprev = prev;
prev = prev->next;
--count;
}
// 区间链表逆置
ListNode* cur = prev->next;
ListNode* next = nullptr;
count = n - m;
while(count)
{
// 断开原链接
prev->next = cur->next;
next = cur->next;
//头插
cur->next = pprev->next;
pprev->next = cur;
cur = next;
--count;
}
return newhead->next;
}
};