Leetcode_堆(1)23 合并k个排序链表,215 数组中的第K个最大元素

目录

23.合并k个排序链表 H

215. 数组中的第K个最大元素


 

23.合并k个排序链表 H

合并 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

方法 1:暴力

想法 & 算法

  • 遍历所有链表,将所有节点的值放到一个数组中。
  • 将这个数组排序,然后遍历所有元素得到正确顺序的值。
  • 用遍历得到的值,创建一个新的有序链表。

方法 2:逐一比较

算法

  • 比较 k 个节点(每个链表的首节点),获得最小值的节点。
  • 将选中的节点接在最终有序链表的后面。

复杂度分析

  • 时间复杂度: O(kN), 其中 k 是链表的数目。

    • 几乎最终有序链表中每个节点的时间开销都为 O(k) (k-1 次比较)。
    • 总共有 N 个节点在最后的链表中。
  • 空间复杂度:

    • O(n) 。创建一个新的链表空间开销为 O(n)O(n) 。
    • O(1) 。重复利用原来的链表节点,每次选择节点时将它直接接在最后返回的链表后面,而不是创建一个新的节点。

方法 3:用优先队列优化方法 2

算法

几乎与上述方法一样,除了将 比较环节 用 优先队列 进行了优化。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    struct cmp{  //对新的数据类型的<进行重写
       bool operator()(ListNode *a,ListNode *b){
          return a->val > b->val;
       }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
       priority_queue<ListNode* ,vector<ListNode*> , cmp> heapk;
       for(auto p:lists){
        if(p!=NULL){
            heapk.push(p);
        }
       }
       ListNode *pHead = new ListNode(-1);
       ListNode *pCur = pHead;
       while(!heapk.empty()){
          ListNode *top = heapk.top();heapk.pop();
          pCur->next = top;
          pCur = pCur->next;
          if(top->next!=NULL){
            heapk.push(top->next);
          } 
       }
       pCur = pHead->next;
       delete pHead;
       return pCur;
    }
};

方法 5:分治

想法 & 算法

  • 将 k 个链表配对并将同一对中的链表合并。
  • 第一轮合并以后,  k 个链表被合并成了 k/2​ 个链表,平均长度为 2N​/k ,然后是k/4​ 个链表,k/8​ 个链表等等。
  • 重复这一过程,直到我们得到了最终的有序链表。

因此,我们在每一次配对合并的过程中都会遍历几乎全部 N 个节点,并重复这一过程 log2​K 次。

类似归并排序的回溯过程,两两合并。  O(Nlog2K)   

public class Test {
	public ListNode mergeKLists(ListNode[] lists) {
		PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>() {
			@Override
			public int compare(ListNode o1, ListNode o2) {
				return o1.val - o2.val;
			}
		});
		for(ListNode e : lists) {
			if(e!=null)
				pq.add(e);
		}
		ListNode head = new ListNode(0);
		head.next = null;
		ListNode tail = head;
		while(!pq.isEmpty()) {
			tail.next = pq.poll();
			tail = tail.next;
			if(tail.next!=null) {
				pq.add(tail.next);
			}
			tail.next = null;
		}
		return head.next;
	}
}

 

 

 

215. 数组中的第K个最大元素

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int,vector<int>,greater<int>> q;
        for(auto it:nums){
            q.push(it);
            if(q.size()>k) q.pop();
        }
        return q.top();
    }
};


 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值