「这是我参与11月更文挑战的第 4 天,活动详情查看:2021最后一次更文挑战」
合并排序的链表
题目来源:LeetCode-剑指 Offer 25. 合并两个排序的链表
题目描述
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的
示例
示例 1
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
提示:
- 0 <= 链表长度 <= 1000
解题:
解法一:开辟新的链表进行合并
思路
个人觉得解链表的题,最好的方式就是画图,因为指针指过来指过去,很容易乱,画图是最清晰的。两个有序链表的合并,最简单的方式就是新开一个链表,找一个哨兵结点充当新链表的虚拟头结点,每次从两个链表中找到较小的那一个,插入到新的链表中,直到两个链表中有一个链表遍历结束,将另一个链表剩余结点,连接到新链表尾部。看图(这种解法,空间复杂度高)
比较简单,不粘贴代码了
解法二:原地合并
思路
- 首先分别有两个指针,指向两个链表的最新节点位置(curr1、curr2)
- 先从两个链表的头节点中找到最小的那个,然后创建一个新的指针(newHead)指向它。并将它的指针向后移动一位
- 定义一个移动指针(moveNode),初始时指向值较小的头节点
- 遍历两个链表,依次比较两个链表的节点值,谁的值小,谁插入到移动指针的后边
- 遍历结束,将非空的那个链表剩余结点,插入到移动指针后边
文字比较难理解,看图
代码
func MergeLinkList(l1 *LinkList.Node, l2 *LinkList.Node) *LinkList.Node {
if l1 == nil && l2 == nil {
return nil
}
if l1 == nil {
return l2
}
if l2 == nil {
return l1
}
curr1 := l1 //链表1当前指向的结点
curr2 := l2 //链表2当前指向的结点
var newHead *LinkList.Node
if curr1.Data <= curr2.Data {
newHead = curr1
curr1 = curr1.Next
} else {
newHead = curr2
curr2 = curr2.Next
}
moveNode := newHead
for ;curr1 != nil && curr2 != nil;moveNode = moveNode.Next {
if curr1.Data < curr2.Data {
moveNode.Next = curr1
curr1 = curr1.Next
} else {
moveNode.Next = curr2
curr2 = curr2.Next
}
}
if curr1 != nil {
moveNode.Next = curr1
}
if curr2 != nil{
moveNode.Next = curr2
}
return newHead
}