25. K 个一组翻转链表

该文章介绍了一种使用递归和翻转单链表的方法来按指定大小k分组反转链表节点的算法。首先确定分组大小,然后反转当前分组,接着递归处理剩余部分,并根据分组大小决定是否反转。时间复杂度为O(n),空间复杂度为O(1)。

方法:模拟

使用翻转单链表的方法,加上递归处理

1、首先,遍历链表确定并记录当前分组的大小

2、反转当前分组的节点。

3、如果反转后还存在剩余节点, 递归反转下一个分组,并将当前分组的尾部连接到下一个分组的头部

4、最后,根据分组大小是否达到 k,分别返回反转后的头部。

具体的思路如下:

  1. 1、首先,遍历链表确定当前分组的大小,即将指针 p 向后移动 k 次,并记录遍历过程中经过的节点个数,保存在变量 groupSize 中。

  2. 2、如果当前分组的大小等于 k,说明该分组需要进行反转操作。

  3. 在当前分组内,使用指针 pre、cur 和 next 来进行反转操作。迭代遍历当前分组的节点,将每个节点的 Next 指针指向前一个节点 pre,完成节点的反转。

  4. 在迭代过程中,同时更新 pre、cur 和 next 的指向,使其指向下一个节点,以便进行下一次的反转。

  5. 3、如果反转后还存在剩余节点,递归地调用 reverseKGroup 函数来处理下一个分组,并将返回的新头部节点连接到当前分组的尾部。

  6. 4、最后,根据分组大小是否达到 k,分别返回反转后的头部。如果分组大小不足 k,则保持不变,返回原始头部。

时间复杂度:O(n),其中 n 为链表的长度。
空间复杂度:O(1),我们只需要建立常数个变量

type ListNode struct{
	Val int
	Next *ListNode
}
func main(){
	// 构造链表 A
	nodeA1 := &ListNode{Val: 1}
	nodeA2 := &ListNode{Val: 2}
	nodeA3 := &ListNode{Val: 3}
	nodeA4 := &ListNode{Val: 4}
	nodeA5 := &ListNode{Val: 5}
	nodeA1.Next = nodeA2
	nodeA2.Next = nodeA3
	nodeA3.Next = nodeA4
	nodeA4.Next = nodeA5

	ansHead:=reverseKGroup(nodeA1,2)
	//头节点开始输出
	for ansHead!=nil{
		fmt.Println(ansNode.Val)
		ansHead=ansNode.Next
	}


}
func reverseKGroup(head *ListNode, k int) *ListNode {
	var pre, next *ListNode
	var cur, p *ListNode = head, head
	groupSize, index := 0, 0

	// 确定当前分组的大小
	for p != nil && groupSize < k {
		p = p.Next
		groupSize++
	}
	if groupSize == k {
		// 反转当前分组的节点
		for cur != nil && index < k {
			next = cur.Next
			cur.Next = pre
			pre = cur
			cur = next
			index++
		}

		if next != nil {
			// 递归反转下一个分组,并将当前分组的尾部连接到下一个分组的头部
			head.Next = reverseKGroup(next, k)
		}
		return pre // 返回当前分组反转后的头部
	} else {
		return head // 当分组大小不足 k 时,保持不变,返回原始头部
	}
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值