Leetcode刷题(第23题)——合并K个升序链表

一、题目

给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

二、示例

//示例一:
输入: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

//示例二
输入:lists = []
输出:[]

//示例三
输入:lists = [[]]
输出:[]

三、本题思路
本题我们可以采用最小堆来解决该问题。
但是什么是最小堆:最小堆就是一个树形结构,父节点的元素的值要小于等于左右子树节点的值。,在js中我们使用数组来表示。
本题为什么可以采用最小堆?
例如:[[1,4,5],[1,3,4],[2,6]],我们首先先取出[1, 4, 5],因为其第一个元素最小,将其第一个元素1,接入新链表中。此时最小堆中的元素为[[1, 3, 4],[2, 6],[4, 5]],然后再取出[1, 3, 4],并将1取出接入新链表。此时最小堆中的元素为[2, 6],[2, 4], [4, 5],然后再取出2…。
四、最小堆结构实现

class MinHeap {
  constructor() {
    this.heap = []
  }
  // 获取父元素的下标
  getParentIndex(index) {
    return (index - 1) >> 1
  }
  // 交换数据
  swap(index1, index2) {
    let temp = this.heap[index1]
    this.heap[index1] = this.heap[index2]
    this.heap[index2] = temp
  }
  // 向上移动数据,将目标数据放到合适的位置
  shiftUp(index) {
    if (index === 0) return
    let parentIndex = this.getParentIndex(index)
    if (this.heap[parentIndex] > this.heap[index]) {
      this.swap(index, parentIndex)
      this.shiftUp(parentIndex)
    }
  }
  // 插入数据
  insert(value) {
    this.heap.push(value)
    this.shiftUp(this.heap.length - 1)
  }
  // 从heap中取出最小的数
  pop() {
    if (this.size() === 1) return this.heap.shift()
    let head = this.heap[0]
    this.heap[0] = this.heap.pop()
    this.shiftDown(0)
    return head
  }
  // 下标为index的节点放入合适的位置
  shiftDown(index) {
    let leftChildIndex = this.getLeftChildIndex(index)
    let rightChildIndex = this.getRightChildIndex(index)
    if (this.heap[leftChildIndex] < this.heap[index]) {
      this.swap(index, leftChildIndex)
      this.shiftDown(leftChildIndex)
    }
    if (this.heap[rightChildIndex] < this.heap[index]) {
      this.swap(index, rightChildIndex)
      this.shiftDown(rightChildIndex)
    }
  }
  // 获取左节点的index
  getLeftChildIndex(index) {
    return index * 2 + 1
  }
  // 获取右节点的index
  getRightChildIndex(index) {
    return index * 2 + 2
  }
  // 获取长度
  size() {
    return this.heap.length
  }
}

let p = new MinHeap()
p.insert(10)
p.insert(1)
p.insert(3)
p.insert(4)
p.insert(9)
console.log(p)
p.pop()
console.log(p)
p.pop()
console.log(p)

五、本题代码实现

class MinHeap {
  constructor() {
    this.heap = []
  }
  // 获取父元素的下标
  getParentIndex(index) {
    return (index - 1) >> 1
  }
  // 交换数据
  swap(index1, index2) {
    let temp = this.heap[index1]
    this.heap[index1] = this.heap[index2]
    this.heap[index2] = temp
  }
  // 向上移动数据,将目标数据放到合适的位置
  shiftUp(index) {
    if (index === 0) return
    let parentIndex = this.getParentIndex(index)
    if ( this.heap[index] &&  this.heap[parentIndex] && this.heap[parentIndex].val > this.heap[index].val) {
      this.swap(index, parentIndex)
      this.shiftUp(parentIndex)
    }
  }
  // 插入数据
  insert(value) {
    this.heap.push(value)
    this.shiftUp(this.heap.length - 1)
  }
  // 从heap中取出最小的数
  pop() {
    if (this.size() === 1) return this.heap.shift()
    let head = this.heap[0]
    this.heap[0] = this.heap.pop()
    this.shiftDown(0)
    return head
  }
  // 下标为index的节点放入合适的位置
  shiftDown(index) {
    let leftChildIndex = this.getLeftChildIndex(index)
    let rightChildIndex = this.getRightChildIndex(index)
    if (this.heap[index] && this.heap[leftChildIndex] && this.heap[leftChildIndex].val < this.heap[index].val) {
      this.swap(index, leftChildIndex)
      this.shiftDown(leftChildIndex)
    }
    if (this.heap[index] && this.heap[rightChildIndex] && this.heap[rightChildIndex].val < this.heap[index].val) {
      this.swap(index, rightChildIndex)
      this.shiftDown(rightChildIndex)
    }
  }
  // 获取左节点的index
  getLeftChildIndex(index) {
    return index * 2 + 1
  }
  // 获取右节点的index
  getRightChildIndex(index) {
    return index * 2 + 2
  }
  // 获取长度
  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) {
    let p = new ListNode(0)
    let res = p
    let heap = new MinHeap()
    for(let item of lists) {
        if(item) heap.insert(item)
    }
    while(heap.size()) {
        let n = heap.pop()
        p.next = n
        p = p.next
        if(n.next) {
            heap.insert(n.next)
        }
    }
    return res.next
};

六、总结
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值