高频算法面试题(八)- 合并两个排序的链表

329 阅读2分钟

「这是我参与11月更文挑战的第 4 天,活动详情查看:2021最后一次更文挑战

合并排序的链表

题目来源LeetCode-剑指 Offer 25. 合并两个排序的链表

题目描述

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的

示例

示例 1

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

提示:

  • 0 <= 链表长度 <= 1000

解题:

解法一:开辟新的链表进行合并

思路

个人觉得解链表的题,最好的方式就是画图,因为指针指过来指过去,很容易乱,画图是最清晰的。两个有序链表的合并,最简单的方式就是新开一个链表,找一个哨兵结点充当新链表的虚拟头结点,每次从两个链表中找到较小的那一个,插入到新的链表中,直到两个链表中有一个链表遍历结束,将另一个链表剩余结点,连接到新链表尾部。看图(这种解法,空间复杂度高) 1.png

比较简单,不粘贴代码了

解法二:原地合并

思路

  1. 首先分别有两个指针,指向两个链表的最新节点位置(curr1、curr2)
  2. 先从两个链表的头节点中找到最小的那个,然后创建一个新的指针(newHead)指向它。并将它的指针向后移动一位
  3. 定义一个移动指针(moveNode),初始时指向值较小的头节点
  4. 遍历两个链表,依次比较两个链表的节点值,谁的值小,谁插入到移动指针的后边
  5. 遍历结束,将非空的那个链表剩余结点,插入到移动指针后边

文字比较难理解,看图

2.png

代码

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
}