目录
143. 重排链表
解析
题解
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
// 56.专题九_链表_重排链表_C++
// 处理边界情况
if (head == nullptr || head->next == nullptr || head->next->next == nullptr) return;
// 1.找到链表的中间节点 - 快慢双指针(一定要画图考虑 slow 的落点在哪里)
ListNode *fast = head;
ListNode *slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
// 画图可以分析出把 slow 后面的链表直接逆序即可
// 2.把 slow 后面的部分给逆序 - 头插法
ListNode* head2 = new ListNode();
ListNode* cur = slow->next;
slow->next = nullptr; // 注意把两个链表给断开
while(cur)
{
ListNode *next = cur->next;
cur->next = head2->next;
head2->next = cur;
cur = next;
}
// 3.合并两个链表 - 双指针
ListNode *ret = new ListNode();
ListNode *prve = ret;
ListNode *cur1 = head, *cur2 = head2->next;
while(cur1) // 只需要判断cur1是否为空就行了,因为第一条链表比较长
{
// 先放第一个链表
prve->next = cur1;
cur1 = cur1->next;
prve = prve->next;
// 再放第二个链表
if (cur2) // 单独判断cur2是否为空
{
prve->next = cur2;
cur2 = cur2->next;
prve = prve->next;
}
}
delete head2;
delete ret;
}
};
23. 合并 K 个升序链表
解析
题解
解法一:优先级队列
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
// 57.专题九_链表_合并 k 个升序链表_C++
// 解法一:优先级队列
struct cmp{
bool operator()(const ListNode* l1, const ListNode* l2)
{
return l1->val > l2->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
// 创建一个小根堆
priority_queue<ListNode*, vector<ListNode*>, cmp> heap;
// 让所有的头节点进入小根堆
for (auto l : lists)
if(l) heap.push(l);
// 合并 K 个有序链表
ListNode *ret = new ListNode(0);
ListNode *prve = ret;
while(!heap.empty())
{
ListNode *t = heap.top();
heap.pop();
prve->next = t;
prve = t;
if(t->next) heap.push(t->next);
}
prve = ret->next;
delete ret;
return prve;
}
};
解法二:分治
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
// 57.专题九_链表_合并 k 个升序链表_C++
// 解法二:分治
ListNode* mergeKLists(vector<ListNode*>& lists) {
return merge(lists, 0, lists.size() - 1);
}
ListNode* merge(vector<ListNode*>& lists, int left, int right)
{
if (left > right) return nullptr;
if (left == right) return lists[left];
// 1.平分数组
int mid = (right - left) / 2 + left;
// [left, mid] [mid + 1, right]
// 2.递归处理左右区间
ListNode* l1 = merge(lists, left, mid);
ListNode* l2 = merge(lists, mid + 1, right);
if(l1 == nullptr) return l2;
if(l2 == nullptr) return l1;
// 3.合并两个有序链表
return mergeTowList(l1, l2);
}
ListNode* mergeTowList(ListNode* l1, ListNode* l2)
{
ListNode head;
ListNode* cur1 = l1, *cur2 = l2, *prve = &head;
head.next = nullptr;
while(cur1 && cur2)
{
if(cur1->val <= cur2->val)
{
prve->next = cur1;
prve = cur1;
cur1 = cur1->next;
}
else
{
prve->next = cur2;
prve = cur2;
cur2 = cur2->next;
}
if(cur1) prve->next = cur1;
if(cur2) prve->next = cur2;
}
return head.next;
}
};
25. K 个一组翻转链表
解析
题解
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
// 58.专题九_链表_K 个一组翻转链表_C++
// 1.先求出需要逆序多少组
int n = 0;
ListNode *cur = head;
while(cur)
{
cur = cur->next;
n++;
}
n /= k;
// 2.重复 n 次:长度为 k 的链表的逆序
ListNode* newHead = new ListNode(0);
ListNode* prve = newHead;
cur = head;
for (int i = 0; i < n; ++i)
{
ListNode *tmp = cur;
for(int j = 0; j < k; ++j)
{
ListNode *next = cur->next;
cur->next = prve->next;
prve->next = cur;
cur = next;
}
prve = tmp;
}
// 把不需要翻转的接上
prve->next = cur;
cur = newHead->next;
delete newHead;
return cur;
}
};