目录
题目:K个一组反转链表
方法一:穿针引线法
思路分析
- 先写一个专门反转的函数
- 算出当前链表长度,再算出需要反转几组:length/k
- 设置一个虚拟头结点指向该链表head
- 始终找到每段要反转的pre、next,把每段反转完之后连上pre、next即可,所以每轮反转要变动的就是pre
- 解释下pre、next、tmp的关系:tmp是要反转链表的头节点,pre.Next=tmp,要反转链表的尾节点.Next=next
- 反转方式说明:使用递归的方法,在每个循环中,将子链表的首尾节点通过递归进行反转。
复杂度:时间复杂度: O ( n ) O(n) O(n)、空间复杂度: O ( 1 ) O(1) O(1)
- 时间复杂度: O ( n ) O(n) O(n)
首先,该函数中使用了一个循环来计算链表的长度,遍历一次链表,时间复杂度是 O ( n ) O(n) O(n),其中 n 是链表的长度。
然后,根据 k 值计算需要反转的次数 times,计算时间复杂度是 O ( 1 ) O(1) O(1)。
在循环中,每次反转长度为 k 的一段链表。在最坏情况下,需要遍历整个链表,每次反转 k 个节点。对于长度为 k 的反转操作,时间复杂度是 O ( k ) O(k) O(k)。因为 k 是一个常量,所以整体的时间复杂度是 O ( n ) O(n) O(n),其中 n 是链表的长度。
综上所述,reverseKGroup 函数的总时间复杂度是 O ( n ) O(n) O(n)。
- 空间复杂度: O ( 1 ) O(1) O(1)
该函数中使用了常量级别的额外空间来存储变量和常数,所以空间复杂度是 O ( 1 ) O(1) O(1)。
Go代码
type ListNode struct {
Val int
Next *ListNode
}
func reverseList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
tmp:=head
newList := reverseList(tmp.Next)
tmp.Next.Next = tmp
tmp.Next = nil
return newList
}
func reverseKGroup(head *ListNode, k int) *ListNode {
if head == nil || head.Next == nil {
return head
}
length := 0
tmp := head
// 得到链表的长度
for tmp != nil {
length++
tmp = tmp.Next
}
dummyHead := &ListNode{}
dummyHead.Next = head
pre := dummyHead
tmp = head
// 算出要反转的次数
times := length/k
for i:=0; i<times; i++ {
// tmp走到k的位置(反转末尾)
for j:=1;j<k;j++ {
tmp = tmp.Next
}
// 保存下一个节点(下一次反转的开头)
next := tmp.Next
tmp.Next = nil
beforeNext := pre.Next
pre.Next = reverseList(beforeNext)
beforeNext.Next = next
pre=beforeNext
tmp=next
}
return dummyHead.Next
}
方法一:头插法
思路分析
- 用虚拟头结点指向head
- 算出链表长度,再算出有多少个要反转的组:length/k
- tmp=head,从表头开始,做k-1次的下一个元素移动到比表头的反转。然后将tmp指向下一段的“表头”,重复该步骤length/k 次
- 解释下pre、tmp的关系:tmp是要反转链表的头节点,pre.Next=tmp
- 反转方式说明:使用迭代的方法,在每个循环中,将后续的 k-1 个节点一个个地从原位置取出,然后将其插入到 pre 节点之后,从而实现链表的反转
复杂度:时间复杂度: O ( n ) O(n) O(n)、空间复杂度: O ( 1 ) O(1) O(1)
Go代码
type ListNode struct {
Val int
Next *ListNode
}
func reverseKGroup(head *ListNode, k int) *ListNode {
if head == nil || head.Next == nil {
return head
}
dummyHead := &ListNode{}
dummyHead.Next = head
pre := dummyHead
tmp := head
length := 0
count := 0
for tmp != nil {
length++
tmp = tmp.Next
}
times := length/k
tmp = head
for i:=1;i<=times;i++ {
for count < k-1 {
next:= tmp.Next
tmp.Next = tmp.Next.Next
next.Next = pre.Next
pre.Next = next
count++
}
count = 0
pre = tmp
tmp = tmp.Next
}
return dummyHead.Next
}