网站备案 个人组网方案做百科权威网站有哪些
网站备案 个人组网方案,做百科权威网站有哪些,pageadmin模板,怎么注册网站 个人合并 kkk 个升序链表是算法面试中的经典题目#xff08;LeetCode 23#xff09;。这道题的核心挑战在于#xff1a;如何高效地从 kkk 个候选节点中每次找出最小的那个。
如果你一个个地合并#xff08;先合并前两个#xff0c;再跟第三个合并…#xff09;#xff0c;效…合并kkk个升序链表是算法面试中的经典题目LeetCode 23。这道题的核心挑战在于如何高效地从kkk个候选节点中每次找出最小的那个。如果你一个个地合并先合并前两个再跟第三个合并…效率会非常低下。最优雅且高效的解法是使用优先队列最小堆Min-Heap。1. 核心思路优先队列法想象一下你有kkk条正在排队的队伍每条队伍都已经按身高排好了。你要把他们合并成一队最快的方法就是让每条队的“排头”都站出来。从这kkk个排头里挑出最矮的一个让他进入新队伍。被挑走的那条队再出一个新的“排头”补上空位。重复这个过程直到所有人排好。2. C 代码实现在 C 中我们使用std::priority_queue。需要注意的是默认的priority_queue是大顶堆我们需要自定义比较函数来构建小顶堆。#includevector#includequeue// 链表节点定义structListNode{intval;ListNode*next;ListNode():val(0),next(nullptr){}ListNode(intx):val(x),next(nullptr){}};classSolution{public:// 自定义比较仿函数让值小的优先级更高即放在堆顶structcompare{booloperator()(ListNode*a,ListNode*b){returna-valb-val;}};ListNode*mergeKLists(std::vectorListNode*lists){// 1. 创建最小堆std::priority_queueListNode*,std::vectorListNode*,comparepq;// 2. 将所有链表的头节点放入堆中for(autohead:lists){if(head)pq.push(head);}// 3. 使用虚拟头节点Dummy Node简化链表构建ListNodedummy(0);ListNode*taildummy;// 4. 不断弹出堆顶最小值并补入其下一个节点while(!pq.empty()){ListNode*smallestpq.top();pq.pop();tail-nextsmallest;tailtail-next;// 如果该节点还有后续把后续塞进堆里继续比if(smallest-next){pq.push(smallest-next);}}returndummy.next;}};3. 复杂度深度解析假设总共有kkk条链表所有链表的节点总数为NNN。时间复杂度O(Nlogk)O(N \log k)O(Nlogk)堆的大小始终保持在kkk以内。每一个节点都会进堆一次、出堆一次。每次堆操作插入/弹出的开销是logk\log klogk。总共NNN个节点所以是O(Nlogk)O(N \log k)O(Nlogk)。空间复杂度O(k)O(k)O(k)优先队列中最多同时存放kkk个节点每条链表贡献一个。4. 还有其他招数吗除了优先队列还有一种非常流行的解法两两合并分治法。逻辑像归并排序Merge Sort一样先两两合并成k/2k/2k/2个再合并成k/4k/4k/4个直到剩下一个。复杂度时间复杂度同样是O(Nlogk)O(N \log k)O(Nlogk)。优点不需要额外的堆空间如果你使用递归或者迭代得当空间复杂度可以优化到O(1)O(1)O(1)如果不计算递归栈的话。