方法:模拟
使用翻转单链表的方法,加上递归处理
1、首先,遍历链表确定并记录当前分组的大小
2、反转当前分组的节点。
3、如果反转后还存在剩余节点, 递归反转下一个分组,并将当前分组的尾部连接到下一个分组的头部
4、最后,根据分组大小是否达到 k,分别返回反转后的头部。
具体的思路如下:
-
1、首先,遍历链表确定当前分组的大小,即将指针 p 向后移动 k 次,并记录遍历过程中经过的节点个数,保存在变量 groupSize 中。
-
2、如果当前分组的大小等于 k,说明该分组需要进行反转操作。
-
在当前分组内,使用指针 pre、cur 和 next 来进行反转操作。迭代遍历当前分组的节点,将每个节点的 Next 指针指向前一个节点 pre,完成节点的反转。
-
在迭代过程中,同时更新 pre、cur 和 next 的指向,使其指向下一个节点,以便进行下一次的反转。
-
3、如果反转后还存在剩余节点,递归地调用 reverseKGroup 函数来处理下一个分组,并将返回的新头部节点连接到当前分组的尾部。
-
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 时,保持不变,返回原始头部
}
}
该文章介绍了一种使用递归和翻转单链表的方法来按指定大小k分组反转链表节点的算法。首先确定分组大小,然后反转当前分组,接着递归处理剩余部分,并根据分组大小决定是否反转。时间复杂度为O(n),空间复杂度为O(1)。
1246

被折叠的 条评论
为什么被折叠?



