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

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

一、题目

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

二、示例

  1. //示例一:
  2. 输入:lists = [[1,4,5],[1,3,4],[2,6]]
  3. 输出:[1,1,2,3,4,4,5,6]
  4. 解释:链表数组如下:
  5. [
  6. 1->4->5,
  7. 1->3->4,
  8. 2->6
  9. ]
  10. 将它们合并到一个有序链表中得到。
  11. 1->1->2->3->4->4->5->6
  12. //示例二
  13. 输入:lists = []
  14. 输出:[]
  15. //示例三
  16. 输入:lists = [[]]
  17. 输出:[]

三、本题思路
本题我们可以采用最小堆来解决该问题。
但是什么是最小堆:最小堆就是一个树形结构,父节点的元素的值要小于等于左右子树节点的值。,在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…。
四、最小堆结构实现

  1. class MinHeap {
  2. constructor() {
  3. this.heap = []
  4. }
  5. // 获取父元素的下标
  6. getParentIndex(index) {
  7. return (index - 1) >> 1
  8. }
  9. // 交换数据
  10. swap(index1, index2) {
  11. let temp = this.heap[index1]
  12. this.heap[index1] = this.heap[index2]
  13. this.heap[index2] = temp
  14. }
  15. // 向上移动数据,将目标数据放到合适的位置
  16. shiftUp(index) {
  17. if (index === 0) return
  18. let parentIndex = this.getParentIndex(index)
  19. if (this.heap[parentIndex] > this.heap[index]) {
  20. this.swap(index, parentIndex)
  21. this.shiftUp(parentIndex)
  22. }
  23. }
  24. // 插入数据
  25. insert(value) {
  26. this.heap.push(value)
  27. this.shiftUp(this.heap.length - 1)
  28. }
  29. // 从heap中取出最小的数
  30. pop() {
  31. if (this.size() === 1) return this.heap.shift()
  32. let head = this.heap[0]
  33. this.heap[0] = this.heap.pop()
  34. this.shiftDown(0)
  35. return head
  36. }
  37. // 下标为index的节点放入合适的位置
  38. shiftDown(index) {
  39. let leftChildIndex = this.getLeftChildIndex(index)
  40. let rightChildIndex = this.getRightChildIndex(index)
  41. if (this.heap[leftChildIndex] < this.heap[index]) {
  42. this.swap(index, leftChildIndex)
  43. this.shiftDown(leftChildIndex)
  44. }
  45. if (this.heap[rightChildIndex] < this.heap[index]) {
  46. this.swap(index, rightChildIndex)
  47. this.shiftDown(rightChildIndex)
  48. }
  49. }
  50. // 获取左节点的index
  51. getLeftChildIndex(index) {
  52. return index * 2 + 1
  53. }
  54. // 获取右节点的index
  55. getRightChildIndex(index) {
  56. return index * 2 + 2
  57. }
  58. // 获取长度
  59. size() {
  60. return this.heap.length
  61. }
  62. }
  63. let p = new MinHeap()
  64. p.insert(10)
  65. p.insert(1)
  66. p.insert(3)
  67. p.insert(4)
  68. p.insert(9)
  69. console.log(p)
  70. p.pop()
  71. console.log(p)
  72. p.pop()
  73. console.log(p)

五、本题代码实现

  1. class MinHeap {
  2. constructor() {
  3. this.heap = []
  4. }
  5. // 获取父元素的下标
  6. getParentIndex(index) {
  7. return (index - 1) >> 1
  8. }
  9. // 交换数据
  10. swap(index1, index2) {
  11. let temp = this.heap[index1]
  12. this.heap[index1] = this.heap[index2]
  13. this.heap[index2] = temp
  14. }
  15. // 向上移动数据,将目标数据放到合适的位置
  16. shiftUp(index) {
  17. if (index === 0) return
  18. let parentIndex = this.getParentIndex(index)
  19. if ( this.heap[index] && this.heap[parentIndex] && this.heap[parentIndex].val > this.heap[index].val) {
  20. this.swap(index, parentIndex)
  21. this.shiftUp(parentIndex)
  22. }
  23. }
  24. // 插入数据
  25. insert(value) {
  26. this.heap.push(value)
  27. this.shiftUp(this.heap.length - 1)
  28. }
  29. // 从heap中取出最小的数
  30. pop() {
  31. if (this.size() === 1) return this.heap.shift()
  32. let head = this.heap[0]
  33. this.heap[0] = this.heap.pop()
  34. this.shiftDown(0)
  35. return head
  36. }
  37. // 下标为index的节点放入合适的位置
  38. shiftDown(index) {
  39. let leftChildIndex = this.getLeftChildIndex(index)
  40. let rightChildIndex = this.getRightChildIndex(index)
  41. if (this.heap[index] && this.heap[leftChildIndex] && this.heap[leftChildIndex].val < this.heap[index].val) {
  42. this.swap(index, leftChildIndex)
  43. this.shiftDown(leftChildIndex)
  44. }
  45. if (this.heap[index] && this.heap[rightChildIndex] && this.heap[rightChildIndex].val < this.heap[index].val) {
  46. this.swap(index, rightChildIndex)
  47. this.shiftDown(rightChildIndex)
  48. }
  49. }
  50. // 获取左节点的index
  51. getLeftChildIndex(index) {
  52. return index * 2 + 1
  53. }
  54. // 获取右节点的index
  55. getRightChildIndex(index) {
  56. return index * 2 + 2
  57. }
  58. // 获取长度
  59. size() {
  60. return this.heap.length
  61. }
  62. }
  63. /**
  64. * Definition for singly-linked list.
  65. * function ListNode(val, next) {
  66. * this.val = (val===undefined ? 0 : val)
  67. * this.next = (next===undefined ? null : next)
  68. * }
  69. */
  70. /**
  71. * @param {ListNode[]} lists
  72. * @return {ListNode}
  73. */
  74. var mergeKLists = function(lists) {
  75. let p = new ListNode(0)
  76. let res = p
  77. let heap = new MinHeap()
  78. for(let item of lists) {
  79. if(item) heap.insert(item)
  80. }
  81. while(heap.size()) {
  82. let n = heap.pop()
  83. p.next = n
  84. p = p.next
  85. if(n.next) {
  86. heap.insert(n.next)
  87. }
  88. }
  89. return res.next
  90. };

六、总结

相关文章