T1. 反转链表
func ReverseList(pHead *ListNode) *ListNode {
var pre, cur, next *ListNode
cur = pHead
if pHead == nil || pHead.Next == nil {
return pHead
}
for cur != nil {
next = cur.Next
cur.Next = pre
pre = cur
cur = next
}
return pre //返回pre而不是cur
}
T2. 链表内指定区间反转
func reverseBetween( head *ListNode , m int , n int ) *ListNode {
if head == nil || head.Next == nil { //do not forget!!!
return head
}
var cur,pre,next,left,right,newHead *ListNode
newHead = &ListNode{-1,head} //设置newHead,防止从head就开始反转,反转后链表头节点就不为head
//pre = &ListNode{-1,head} //pre.Next = head报错?pre都没给,哪来的pre.Next
pre = newHead
for i := 1; i < m; i++ {
pre = pre.Next
}
left = pre
cur = pre.Next
for i := m; i <= n; i++ { //go中没有++i
next = cur.Next
cur.Next = pre
pre = cur
cur = next
}
right = cur
left.Next.Next = right //反转部分重新连接
left.Next = pre
return newHead.Next //newHead.Next才是反转后的头节点
}
复习一下指针,p *p &p
T3. 链表中节点每k个一组反转
时间复杂度O(2k+n) 空间复杂度O(1) 思路: 1. 先找反转后头节点 2. 递归反转每个区间并连接 3. 递归结束,返回头节点
func reverseKGroup(head *ListNode, k int) *ListNode {
if head == nil {
return head
}
newHead := &ListNode{-1, head}
for count := 1; count < k; count++ { //先找新链表头节点
head = head.Next
if head == nil { //不能反转则返回head
return newHead.Next
}
}
reverse(newHead, k)
return head
}
func reverse(head *ListNode, k int) int {
if head == nil || head.Next == nil { //反转终止
return 0
}
var newHead, pre, cur, next *ListNode
pre = nil
cur = head.Next
for count := 1; count <= k; count++ {
next = cur.Next
cur.Next = pre
pre = cur
cur = next
if cur == nil && count != k { //节点不足k个,再次反转回来
cur = pre //不要总把pre cur的位置搞错!!!!
pre = nil
for ; count > 0; count-- {
next = cur.Next
cur.Next = pre
pre = cur
cur = next
}
return 0 //反转终止,输出反转后链表
}
}
newHead = head.Next
head.Next = pre //前一个区间连到当前区间
newHead.Next = cur //当前指向下一个区间
reverse(newHead, k) //递归
return 0
}
注意:
1. 每次反转时注意pre cur的位置
2. 递归别忘了给返回值做终止条件
T4. 判断是否回文
链表经常用双指针来找mid。
func isPail(head *ListNode) bool {
if head == nil || head.Next == nil {
return true
}
fast := &ListNode{-1, head}
slow := fast
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
}
mid := reverse(slow.Next)
for head != nil && mid != nil {
if head.Val != mid.Val {
return false
}
head = head.Next
mid = mid.Next
}
return true
}
func reverse(head *ListNode) *ListNode {
var pre, cur, next *ListNode
pre = nil
cur = head
for cur != nil {
next = cur.Next
cur.Next = pre
pre = cur
cur = next
}
return pre
}