Leetcode 23. Merge k Sorted Lists

  • Leetcode 23. Merge k Sorted Lists
    • 题目
    • 题目解析
    • 代码
    • 链表类题目总结

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中实现的setmap这些都是排序的结构,因此直接应用即可。
接下来就是编程的问题了,我们需要的是把节点放入到set中,但如何重定义他的比较函数呢,因为重载运算符必须是对象,不能直接对指针重载运算符,因此我们用一个pair结构,结构的第一个元素是链表节点,第二个参数是链表的值,然后重载运算符就可以了。由于可能会有重复值,因此需要用有重复值的set

代码

经过上面的分析,代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
// 定义结构并重载运算符
using PointX = pairint>;
bool operator<(const PointX &a, const PointX &b)
{
    return a.second < b.second;
}

class Solution {
public:
    ListNode* mergeKLists(vector& lists) {
        multiset> 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. 注意尾巴指针置空,否则会无限循环

你可能感兴趣的:(Leetcode,leetcode)