删除链表的倒数第N个节点
题干:给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
测试地址:. - 力扣(LeetCode)
双指针:快指针先走个n步,然后两个指针一起走,快指针走到末尾了,这个时候慢指针也就到了倒数的第n个节点了。比如倒数第一个,那就fast走到fast.next是nil的时候,慢指针就在倒数第二个,那就让slow.next=slow.next.next就可以了
func removeNthFromEnd(head *ListNode, n int) *ListNode {
dummyhead := &ListNode{
Val: 0,
Next: head,
}
var fast, slow *ListNode
fast, slow = dummyhead, dummyhead
for i := 0; i < n; i++ {
fast = fast.Next
}
for fast.Next != nil {
fast = fast.Next
slow = slow.Next
}
slow.Next = slow.Next.Next
return dummyhead.Next
}
链表相交
题干:给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
测试地址:. - 力扣(LeetCode)
核心在于如果相交,那么就是从某个节点开始两个节点后面的节点全部相等,也就意味两个链表是尾对齐的,而两个链表差值的地方一定不是相交的。所以忽略两个链表长度差的部分,从相等的部分往后遍历即可。
func getIntersectionNode(headA, headB *ListNode) *ListNode {
if headA == nil || headB==nil{
return nil
}
var cura, curb = headA, headB
var lenA, lenB int
for cura.Next != nil || curb.Next != nil {
if cura.Next != nil {
cura = cura.Next
lenA++
}
if curb.Next != nil {
curb = curb.Next
lenB++
}
}
var Difference = lenA - lenB
if Difference > 0 {
for i := 0; i < Difference; i++ {
headA = headA.Next
}
} else {
for i := 0; i < (-Difference); i++ {
headB = headB.Next
}
}
for headA != nil && headB != nil {
if headA == headB {
return headA
}
headA = headA.Next
headB = headB.Next
}
return nil
}
环形链表II
题干:给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
测试地址:. - 力扣(LeetCode)
推理过程可以看原文:代码随想录
不过一张图就可以了,背着算了
func detectCycle(head *ListNode) *ListNode {
fast, slow := head, head
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
if fast == slow { //有环
fast = head
for fast != slow {
fast = fast.Next
slow = slow.Next
}
return fast
}
}
return nil
}
链表总结
善用虚拟头结点,可以少考虑要改变首节点的情况。