LeetCode 92 反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

示例 1:

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例 2:

输入:head = [5], left = 1, right = 1
输出:[5]

提示:

  • 链表中节点数目为 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n

进阶: 你可以使用一趟扫描完成反转吗?

解题:

func reverseBetween(head *ListNode, left int, right int) *ListNode {
	dummy := &ListNode{0, head}
	start, i := dummy, 0
	r, end, begin := &ListNode{}, &ListNode{}, &ListNode{}
	for i <= right {
		if i == left {
			end = start
			r = start
			start = start.Next
		} else if i > left {
			temp := start.Next
			start.Next = r
			r = start
			start = temp
		} else {
			begin = start
			start = start.Next
		}
		i++
	}
	end.Next = start
	begin.Next = r
	return dummy.Next
}

官方解答:

1.穿针引线

func reverseLinkedList(head *ListNode) {
	var pre *ListNode
	cur := head
	for cur != nil {
		next := cur.Next
		cur.Next = pre
		pre = cur
		cur = next
	}
}

func reverseBetween(head *ListNode, left int, right int) *ListNode {
	// 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
	dummyNode := &ListNode{Val: -1}
	dummyNode.Next = head

	pre := dummyNode
	// 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
	// 建议写在 for 循环里,语义清晰
	for i := 0; i < left-1; i++ {
		pre = pre.Next
	}

	// 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
	rightNode := pre
	for i := 0; i < right-left+1; i++ {
		rightNode = rightNode.Next
	}

	// 第 3 步:切断出一个子链表(截取链表)
	leftNode := pre.Next
	curr := rightNode.Next

	// 注意:切断链接
	pre.Next = nil
	rightNode.Next = nil

	// 第 4 步:同第 206 题,反转链表的子区间
	reverseLinkedList(leftNode)

	// 第 5 步:接回到原来的链表中
	pre.Next = rightNode
	leftNode.Next = curr
	return dummyNode.Next
}

2.一次遍历「穿针引线」反转链表(头插法)

func reverseBetween(head *ListNode, left, right int) *ListNode {
	// 设置 dummyNode 是这一类问题的一般做法
	dummyNode := &ListNode{Val: -1}
	dummyNode.Next = head
	pre := dummyNode
	for i := 0; i < left-1; i++ {
		pre = pre.Next
	}
	cur := pre.Next
	for i := 0; i < right-left; i++ {
		next := cur.Next
		cur.Next = next.Next
		next.Next = pre.Next
		pre.Next = next
	}
	return dummyNode.Next
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注