• 23、合并K个升序链表 | JS堆


    给你一个链表数组,每个链表都已经按升序排列。

    请你将所有链表合并到一个升序链表中,返回合并后的链表。

    示例 1:

    输入:lists = [[1,4,5],[1,3,4],[2,6]]
    输出:[1,1,2,3,4,4,5,6]
    解释:链表数组如下:
    [
    1->4->5,
    1->3->4,
    2->6
    ]
    将它们合并到一个有序链表中得到。
    1->1->2->3->4->4->5->6


    示例 2:

    输入:lists = []
    输出:[]


    示例 3:

    输入:lists = [[]]
    输出:[]
     

    提示:

    k == lists.length
    0 <= k <= 10^4
    0 <= lists[i].length <= 500
    -10^4 <= lists[i][j] <= 10^4
    lists[i] 按 升序 排列
    lists[i].length 的总和不超过 10^4

    class MinHeap {
      constructor(){
        this.heap = [];
      }
      swap(i1, i2){
        const temp = this.heap[i1];
        this.heap[i1] = this.heap[i2];
        this.heap[i2] = temp;
      }
      getParentIndex(i){  //获取父节点的值
        return (i-1) >> 1;  //二进制右移相当于除以2
      }
      getLeftIndex(i) {  //获取左结点
        return i * 2 + 1;
      }
      getRightIndex(i) {  //获取右结点
        return i * 2 + 2;
      }
    
      shiftUp(index){   //需要让父节点不断小于它的子节点
        if(index == 0){ return; }  //如果已经是根结点了就不用找了
        const parentIndex = this.getParentIndex(index);
        if(this.heap[parentIndex] && this.heap[parentIndex].val > this.heap[index].val){
          this.swap(parentIndex, index);  //如果父节点的值大于子节点则进行交换
          this.shiftUp(parentIndex)
        }
      }
      insert(value){  //插入,添加的方法
        this.heap.push(value);
        this.shiftUp(this.heap.length - 1);  //shiftUp就是上移操作,接收参数是上移时的下标
      }
      shiftDown(index){  //下移节点,直到子节点都大于当前节点的值
        // 需要获取它的左右子节点
        const leftIndex = this.getLeftIndex(index);
        const rightIndex = this.getRightIndex(index);
        if(this.heap[leftIndex] && this.heap[leftIndex].val < this.heap[index].val){  //小顶堆,父节点小于子节点
          this.swap(leftIndex, index);
          this.shiftDown(leftIndex);  //迭代,直到找到合适的位置
        }
        if(this.heap[rightIndex] && this.heap[rightIndex].val < this.heap[index].val){  //小顶堆,父节点小于子节点
          this.swap(rightIndex, index);
          this.shiftDown(rightIndex);  //迭代,直到找到合适的位置
        }
      }
    
      pop(){   //下移方法
        if(this.size() === 1) return this.heap.shift();
        const top = this.heap[0];
        this.heap[0] = this.heap.pop();  // 把数组的最后一位转移到头部,相当于变相删除堆顶
        this.shiftDown(0);  //传什么下标,就对那个进行下移操作
        return top;  //返回堆顶
      }
      peek(){ //获取堆顶,返回数组的头部
        return this.heap[0];
      }
      size(){  // 获取堆的大小
        return this.heap.length;
      }
    }
    /**
     * 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) {
        const res = new ListNode(0);
        let p = res;
        const h = new MinHeap();
        lists.forEach(l => {
            if(l) h.insert(l);
        })
        while(h.size()){  //堆有值的情况下不断的循环
            const n = h.pop();
            p.next = n;
            p = p.next;  //方便接后面的结点
            if(n.next) h.insert(n.next);  //把下一个结点插入
        }
        return res.next; //因为都要接到新建的链表后面
    };
  • 相关阅读:
    20160227.CCPP体系详解(0037天)
    MinerUtil.java 爬虫工具类
    MinerUrl.java 解析页面后存储URL类
    MinerThreadPool.java 线程池
    MinerStoreThread.java 存储线程
    MinerQueue.java 访问队列
    MinerMonitorThread.java 监控线程
    MinerHtmlThread.java 爬取页面线程
    上班跟打DotA感觉差不多?姑娘你没事儿吧
    7月3日云栖精选夜读:强大的PyTorch:10分钟让你了解深度学习领域新流行的框架
  • 原文地址:https://www.cnblogs.com/oaoa/p/15037719.html
Copyright © 2020-2023  润新知