刷题笔记——链表合并

刷题笔记——链表合并

今天带来leetcode23题的刷题笔记。这是一道困难题,但整体来说是比较容易的一道。

先来看看原题描述:

23. Merge k Sorted Lists

题目

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Example :

Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6
题目大意

合并 K 个有序链表

解题思路

借助分治的思想,把 K 个有序链表两两合并即可。相当于是第 21 题的加强版。

解题前先看看21题

21. 合并两个有序链表

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

这道题是道简单题。操作起来也方便,利用和归并排序相同的方式即可。

上手极易,上代码:

func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
    //这里声明一个root指向第一个结点,最终返回root.Next即可。以防结点的变化,适用于很多情况
    root := &ListNode{}
	node := root
	for l1 != nil && l2 != nil {
		if l1.Val < l2.Val {
			node.Next = l1
			l1 = l1.Next
		} else {
			node.Next = l2
			l2 = l2.Next
		}
		node = node.Next
	}
    //循环完,防止出现某条链表没有遍历完的情况,需要额外判断一下。
	if l1 != nil {
		node.Next = l1
	}
	if l2 != nil {
		node.Next = l2
	}
	return root.Next
}

这道题需要注意的地方就是注释两点。

再看看23题,k条链表,那么自然不能简单像21题如此处理了。需要对所有链表循环比较。

话不多说,上代码:

func mergeKLists(lists []*ListNode) *ListNode {
    // 同样为返回值而声明
    root := &ListNode{}
    if len(lists) == 0 {
        return root.Next
    }
	node := root
	index := 0
    

	for node != nil {
		// num为了获取当前最小值
        num := math.MaxInt64
		for k, v := range lists {
            // 判v空即可保证所有节点都被遍历到,不多也不少
			if v != nil && v.Val <= num {
				num = lists[k].Val
				index = k
			}
		}
		if lists[index] == nil {
			break
		}
		node.Next = lists[index]
		node = node.Next
		lists[index] = lists[index].Next
	}

	return root.Next
}

这道题如此解法的注意也写在注释上了。

循环虽然好想,但其实代码书写的时候不太容易。那么其他的解题方案?

分治法

分治法是解决此题的较好的方法。

利用21题的两两合并的函数。(这里两两合并也使用分治思想)

上代码:

func mergeKLists(lists []*ListNode) *ListNode {
	length := len(lists)
	if length < 1 {
		return nil
	}
	if length == 1 {
		return lists[0]	
	}
	num := length / 2
	left := mergeKLists(lists[:num])
	right := mergeKLists(lists[num:])
	return mergeTwoLists1(left, right)
}

func mergeTwoLists1(l1 *ListNode, l2 *ListNode) *ListNode {
	if l1 == nil {
		return l2
	}
	if l2 == nil {
		return l1
	}
	if l1.Val < l2.Val {
		l1.Next = mergeTwoLists1(l1.Next, l2)
		return l1
	}
	l2.Next = mergeTwoLists1(l1, l2.Next)
	return l2
}

此种解法借助分治的思想,把k个有序链表两两合并即可。虽然思路上比较难,但代码书写上比较容易。


有兴趣的关注我的公众号,一起学习交流啊
刷题笔记——链表合并_第1张图片

你可能感兴趣的:(#,算法刷题笔记)