23.合并K个升序链表

98 阅读1分钟

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

请你将所有链表合并到一个升序链表中,返回合并后的链表。
解法:
方法一:所有的数字放到一个最大heap中,

func mergeKLists(lists []*ListNode) *ListNode {

	heap := NewHeap(500 * len(lists))
	for index := range lists {
		list := lists[index]
		if list == nil {
			continue
		}
		
		for list != nil {
			heap.Push(list.Val)
			list = list.Next
		}
	}

	dummy := &ListNode{}
	head := dummy
	// 从heap中取最小的值
	for !heap.IsEmpty() {
		head.Next = &ListNode{
			Val: heap.DeleteRoot(),
		}
		head = head.Next
	}
	return dummy.Next
}

// 以下为heap的实现
type Heap struct {
	Array    []int
	N        int
	Capacity int
}

func NewHeap(n int) *Heap {
	return &Heap{
		Array:    make([]int, 1),
		Capacity: n,
	}
}

func (h *Heap) Push(v int) {
	if h.N < h.Capacity {
		h.Array = append(h.Array, v)
		h.N++
		h.swim(h.N)
	} else {
		if v > h.Array[1] {
			h.Array[1] = v
			h.sink(1)
		}
	}

}

func (h *Heap) Top() int {
	return h.Array[1]
}

func (h *Heap) IsEmpty() bool {
	return len(h.Array) < 2
}

// 删除根节点的值
func (h *Heap) DeleteRoot() int {
	ret := h.Array[1]
	h.swap(1, h.N)
	h.Array = h.Array[:h.N]
	h.N--
	h.sink(1)
	return ret
}

// 节点i的父节点比它小时,执行swim,节点i上浮,
func (h *Heap) sink(i int) {
	current := i
	child := 2 * current
	for child <= h.N {
		// 右子节点一定比左子节点大,交换右子节点和根节点一定满足堆的条件
		if child+1 <= h.N && h.less(child, child+1) {
			child = child + 1
		}
		if !h.less(current, child) {
			break
		}
		h.swap(current, child)
		current = child
		child = 2 * current
	}
}

// 节点i的子节点比它大时,执行sink,节点i下沉
func (h *Heap) swim(i int) {
	current := i
	parent := current / 2
	for parent > 0 {
		if !h.less(parent, current) {
			break
		}
		h.swap(current, parent)
		current = parent
		parent = current / 2
	}
}
func (h *Heap) less(i int, j int) bool {
	return h.Array[i] > h.Array[j]
}
func (h *Heap) swap(i int, j int) {
	h.Array[i], h.Array[j] = h.Array[j], h.Array[i]
}

方法二: 分治 每次合并2个数组,直到所有数组合并