合并K个有序链表

31 阅读1分钟

方法一:水平扫描法

将合并 k 个有序链表看为多个合并两个有序链表

func mergeKLists(lists []*ListNode) *ListNode {
	head := &ListNode{}
	node := head.Next
	for _, item := range lists {
		node = mergeTwoLists(node, item)
	}
	return node
}

func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
	head := &ListNode{}
	current := head
	for list1 != nil && list2 != nil {
		if list1.Val < list2.Val {
			current.Next = list1
			list1 = list1.Next
		} else {
			current.Next = list2
			list2 = list2.Next
		}
		current = current.Next
	}
	if list1 != nil {
		current.Next = list1
	} else if list2 != nil {
		current.Next = list2
	}
	//return current.Next
	//注意返回值!
	return head.Next
}

方法二:分治法

分治法在合并k个升序链表时通常比水平扫描方法更快。分治法通过递归地将k个链表分为两半,然后合并,这样减少了重复比较的次数,时间复杂度为O(Nlogk),其中N是所有链表中元素的总数,k是链表的数量。

相比之下,水平扫描方法每次合并两个链表,总共需要合并k-1次,时间复杂度为O(kN),在k较大时,性能较分治法差。因此,对于大量链表的合并问题,分治法更为高效。

func mergeKLists(lists []*ListNode) *ListNode {
	if len(lists) < 1 {
		return nil
	}
	//切两半
	return mergeRangeLists(lists, 0, len(lists)-1)
}
func mergeRangeLists(lists []*ListNode, start, end int) *ListNode {
	if start >= end {
		return lists[start]
	}
	//这里起始应该是start,而不是0
	//left := mergeRangeLists(lists, 0, (end-start)/2)
	//right := mergeRangeLists(lists, (end-start)/2+1, end)
	left := mergeRangeLists(lists, start, start+(end-start)/2)
	right := mergeRangeLists(lists, start+(end-start)/2+1, end)
	return mergeTwoLists(left, right)
}

func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
	head := &ListNode{}
	current := head
	for list1 != nil && list2 != nil {
		if list1.Val < list2.Val {
			current.Next = list1
			list1 = list1.Next
		} else {
			current.Next = list2
			list2 = list2.Next
		}
		current = current.Next
	}
	if list1 != nil {
		current.Next = list1
	} else if list2 != nil {
		current.Next = list2
	}
	//return current.Next
	//注意返回值!
	return head.Next
}