[路飞]_你不知道的力扣刷题技巧(Javascript)-优先队列

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

前言

如果你经常在力扣刷算法题,并且如果你是一名前端开发者,或许你会使用Javascript来做题,Javascript或许不像C++或Java有一些已经封装好的数据结构,比如栈,队列,可能都需要手动去实现。其实很多人还不知道力扣其实提供了一些轮子供我们使用。

图片.png

  • 这个地方比较隐蔽点击以后

图片.png

  • 出现的提示框告诉我们,力扣已经内置了一个lodash.js的库,这个应该大家比较熟悉的库,就不多赘述了。
  • 重点来说说第二个优先队列

堆与优先队列

说到优先队列就不得不先说一下堆的概念

  • 百度百科:堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。
  • 堆又可分为大顶(根)堆和小顶(根)堆
  • 以大顶堆为例:对于任意一个结点,都要求根的值 大于或等于 其所有子树结点的值,小顶对则与其相反

图片.png

优先队列

  • 百度百科:普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。
  • 在Javascript中堆的概念可以用数组实现,关于如何自己手动实现一个堆,将在后序单独写一篇文章。
  • 关于如何使用,力扣提供的priority-queue 文档写的已经比较详细

堆-优先队列的作用

一句话:堆适合维护:集合最值

实操力扣算法题

废话不多说,直接来看一道力扣的困难题 23. 合并K个升序链表

图片.png

  • 分析

如果使用暴力解法,每次都需要遍历一次数组,得到头节点最小的链表,然后把这个值插入到新链表最后,然后再去掉这个头再将链表放回数组中,再循环进行查找,这样不出意外力扣判题是会超时的

如果使用优先队列,每次循环都可以从队首得到头节点最小的那个链表元素,如果所有链表的长度总和为k,则算法的空间复杂度为O(k)

  • 代码实现
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function(lists) {
    var heap = new MinPriorityQueue({ // 小顶堆
        priority: (bid) => bid.val // 堆顶为头节点最小的那个链表
    })
    // 依次入堆
    for(var list of lists) {
        if(!list) continue
        heap.enqueue(list)
    }
    var ret = new ListNode() //虚拟头节点,方便返回
    var p = ret // 指针
    // 每次从堆顶拿出一个链表,将头节点拿出来链接到新链表最后,然后再塞回堆中
    while(heap.size()) {
        var cur = heap.dequeue().element // 弹出堆顶元素
        p.next = cur
        p = p.next
        if(cur.next) heap.enqueue(cur.next) //如果链表还没走到最后,再塞回堆中
    }
    p.next = null //链表最后指向null
    return ret.next
};
复制代码

--- end ---

Guess you like

Origin juejin.im/post/7031570472231927845