高频算法面试题(十)- 链表中的节点每k个一组翻转

117 阅读3分钟

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

K个一组翻转链表

题目来源LeetCode-K 个一组翻转链表

题目描述

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表

k 是一个正整数,它的值小于或等于链表的长度

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序

进阶:

  • 你可以设计一个只使用常数额外空间的算法来解决此问题吗?
  • 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例

示例 1

2.png

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

示例 2

3.png

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

示例 3

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

示例 4

输入:head = [1], k = 1
输出:[1]

提示:

  • 列表中节点的数量在范围 sz 内
  • 1 <= sz <= 5000
  • 0 <= Node.val <= 1000
  • 1 <= k <= sz

解题

其实这道题跟翻转链表思路差不多,现在只不过是分段翻转,如果你不太清楚翻转链表过程是什么样的,建议先回顾一下(快速通道

思路

创建一个哨兵结点(dummy),哨兵结点的next指针指向链表的头结点,对原链表进行每k组一次的遍历,并将每k个元素按照头插法插入到哨兵结点的后边。每插入k个结点后,更新哨兵结点到改组(每k个一组)结点的尾节点,然后再从原链表中遍历k个节点过来,重复下去,直到遍历到结尾(不足k的部分不翻转)

  1. 定义start、end结点,start指向每组结点的头结点,end指向每组结点的尾节点
  2. 定义pre结点、next结点,pre结点指向start结点的前驱结点,next指向end的后继结点
  3. 每翻转一组,更新pre为翻转完成的链表的尾节点、start为pre的后继结点,将翻转完成部分的链表和待反转部分的链表连接
  4. 期间如果end为空,则终止

4.png 图中只画了一轮,其余过程都是一样的(链表的题不画图的话,稍微复杂一点,就很容易指错)

代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseKGroup(head *ListNode, k int) *ListNode {
    dummy := &ListNode{}
	pre := dummy
	end := dummy

	dummy.Next = head
	for end.Next != nil {
		for i :=0; i < k && end != nil; i++ {
			end = end.Next
		}
		if end == nil {
			break
		}

		start := pre.Next
		next := end.Next
		end.Next = nil //这个是为了方便反转这个k个节点
		pre.Next = reverseList(start) //前边部分与刚反转完的这部分连接
		start.Next = next // 反转之后start变成了这个k组中的最后一个结点的位置,所以让他的Next指针指向next结点,将后边未翻转的连接起来
		pre = start
		end = pre
	}

	return dummy.Next
}

func reverseList(head *ListNode) *ListNode {
	if head == nil  || head.Next == nil{
		return head
	}

	newHead := &ListNode{}
	newHead.Next = head
	prevNode := newHead.Next
	currentNode := prevNode.Next
	for currentNode != nil {
		prevNode.Next = currentNode.Next
		currentNode.Next = newHead.Next
		newHead.Next = currentNode
		currentNode = prevNode.Next
	}
	head = newHead.Next

	return head
}