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

x33g5p2x  于2022-02-28 转载在 其他  
字(3.5k)|赞(0)|评价(0)|浏览(168)

一、题目

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

二、示例

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

六、总结

相关文章

微信公众号

最新文章

更多