Leetcode 23. Merge k Sorted Lists
题目
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
题目解析
题目的意思很简单,合并多个排序的链表,看起来和归并排序非常相似,可以说基本相同的。按照常规的思路,设立一个链表头,然后依次比较这k
个链表中较小的一个,挂在这个链表头上。很快就写出代码,但果然,肯定是超时的,hard
的应该没这么简单==
分析一下,时间主要花在每次扩展时对这些链表头进行遍历,如果加快搜索呢,当然是进行排序。我们需要维护的是一个已经排序的结构,每次能够迅速找到最小值,可以选择的是排序的二叉树,堆等。考虑到STL中实现的set
,map
这些都是排序的结构,因此直接应用即可。
接下来就是编程的问题了,我们需要的是把节点放入到set
中,但如何重定义他的比较函数呢,因为重载运算符必须是对象,不能直接对指针重载运算符,因此我们用一个pair
结构,结构的第一个元素是链表节点,第二个参数是链表的值,然后重载运算符就可以了。由于可能会有重复值,因此需要用有重复值的set
代码
经过上面的分析,代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// 定义结构并重载运算符
using PointX = pair<ListNode *, int>;
bool operator<(const PointX &a, const PointX &b)
{
return a.second < b.second;
}
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
multiset<PointX, less<PointX>> mpset;
for (auto i : lists)
if(i) // 对应于[[]]的测试用力
mpset.insert(make_pair(i,i->val));
ListNode * tmp = nullptr;
ListNode * head = nullptr;
while (!mpset.empty())
{
auto it = mpset.begin();
if (tmp == nullptr) // 确定表头,head记录表头
{
tmp = it->first;
head = tmp;
}
else
{
tmp->next = it->first;
tmp = tmp->next;
}
auto ptr = it->first;
mpset.erase(it); // 删除节点,注意是删除迭代器,不然重复值可能会全部删除了
if (ptr->next)
{
mpset.insert(make_pair(ptr->next, ptr->next->val));
}
}
if(tmp) // 特殊情况判断
tmp->next = nullptr;
return head;
}
};
链表类题目总结
最近准备秋招,做了一些链表类的题目,总体感觉链表类题目容易出错,需要考虑一些特殊的情况,总结如下:
1. 获得->next
和->val
前,需要判断节点是否为空
2. 可以增加一个头节点,减少头节点是否为空的判断,返回的时候返回nhead->next
就可以
3. 判断题目需求链表分成几段,记录每一段的开头和结尾,先在纸上画出图,确定要使用几个指针来记录
4. 判断输入节点是否为空
5. 注意尾巴指针置空,否则会无限循环