反转链表示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
思路
- 备份 旧head->next
- head->next更新为新节点
- head 变为 旧head->next
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* p = nullptr;
while(head){
ListNode* tmp = head->next;//旧head->next备份
head->next = p;//新 head->next
p = head;//p更新
head = tmp;//head 变为 旧head->next
}
return p;
}
};
链表交换示例
Leetcode24. 两两交换链表中的节点
给定 1->2->3->4, 你应该返回 2->1->4->3.
- 和反转链表思路相同,也是从头节点遍历,交换链表顺序
- 不同的是,这一题要交换两个链表,会有两个临时变量,进行三次操作
- 这三次操作分别是:
![图片来自leetcode](https://img2020.cnblogs.com/blog/2146166/202010/2146166-20201013094043850-428568591.png)
- 注意:node2的next更新一定是要在node1的next更新之后,否则node2->next=node1, node1->next=node2, 这样就成了环,从而进入死循环
- 注意:交换的是head->next 和 head->next->next, 那head咋办?为了要让head能成为一个节点的next,所以定义一个头节点,该节点的next指向head
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* first = new ListNode(0);
first->next = head;
ListNode* p = first;
while(p->next && p->next->next){
ListNode* tmp1 = p->next;
ListNode* tmp2 = p->next->next;
p->next = tmp2;
tmp1->next = tmp2->next;
tmp2->next = tmp1;
p = tmp1;
}
return first->next;
}
};
k 个一组反转链表
25. K 个一组翻转链表
- 上边相当于2个一组翻转链表
- k 个一组的话相当于先每k个切一刀,把这段翻转(子链表反转),再接回原处
class Solution {
public:
//翻转某一段
pair<ListNode*, ListNode*> reverse(ListNode* head, ListNode* tail){
ListNode* p = tail->next;
ListNode* head_tmp = head;
while(p != tail){
ListNode* tmp = head->next;
head->next = p;
p = head;
head = tmp;
}
return {p, head_tmp};
}
ListNode* reverseKGroup(ListNode* head, int k) {
if(!head) return nullptr;
//
ListNode hair(0);
hair.next = head;
ListNode* pre = &hair;
while(head){
ListNode* tail = pre;
for(int i = 0; i < k; ++i){
tail = tail->next;
if(!tail){
return hair.next;//不足k个,保持原有顺序
}
}
//备份
ListNode* tmp = tail->next;
//翻转
auto ll = reverse(head, tail);
head = ll.first;
tail = ll.second;
//接回来
pre->next = head;
tail->next = tmp;
//pre、tail移动
pre = tail;
head = tail->next;
}
return hair.next;
}
};