LeetCode 典型链表 Golang 题解

565 阅读2分钟

【206】反转链表

// 解法 1
func reverseList(head *ListNode) *ListNode {
    var prev *ListNode
    for head != nil {
        head, head.Next, prev = head.Next, prev, head
    }
    return prev
}

// 解法 2
func reverseList(head *ListNode) *ListNode {
	var behind *ListNode
	for head != nil {
		next := head.Next
		head.Next = behind
		behind = head
		head = next
	}
	return behind
}

【92】反转链表的一部分

func reverseLinkedList(head *ListNode) {
    var prev *ListNode
    for head != nil {
        head, head.Next, prev = head.Next, prev, head
    }
}

func reverseBetween(head *ListNode, left, right int) *ListNode {
    // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
    dummyNode := &ListNode{Val: -1}
    dummyNode.Next = head

    pre := dummyNode
    // 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
    // 建议写在 for 循环里,语义清晰
    for i := 0; i < left-1; i++ {
        pre = pre.Next
    }

    // 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
    rightNode := pre
    for i := 0; i < right-left+1; i++ {
        rightNode = rightNode.Next
    }

    // 第 3 步:切断出一个子链表(截取链表)
    leftNode := pre.Next
    curr := rightNode.Next

    // 注意:切断链接
    pre.Next = nil
    rightNode.Next = nil

    // 第 4 步:反转链表的子区间
    reverseLinkedList(leftNode)

    // 第 5 步:接回到原来的链表中
    pre.Next = rightNode
    leftNode.Next = curr
    return dummyNode.Next
}

【25】K个一组反转链表

func reverseKGroup(head *ListNode, k int) *ListNode {
	node := head
	for i := 0; i < k; i++ {
		if node == nil {
			return head
		}
		node = node.Next
	}
	newHead := reverse(head, node)
	head.Next = reverseKGroup(node, k)
	return newHead
}

func reverse(first *ListNode, last *ListNode) *ListNode {
    prev := last
    for first != last {
        first, first.Next, prev = first.Next, prev, first
    }
    return prev
}

【234】回文链表

func reverseList(head *ListNode) *ListNode {
    var prev *ListNode
    for head != nil {
        next := head.Next
        head.Next = prev
        prev = head
        head = next
    }
    return prev
}

func endOfFirstHalf(head *ListNode) *ListNode {
    fast := head
    slow := head
    for fast.Next != nil && fast.Next.Next != nil {
        fast = fast.Next.Next
        slow = slow.Next
    }
    return slow
}

func isPalindrome(head *ListNode) bool {
    if head == nil {
        return true
    }

    // 找到前半部分链表的尾节点并反转后半部分链表
    firstHalfEnd := endOfFirstHalf(head)
    secondHalfStart := reverseList(firstHalfEnd.Next)

    // 判断是否回文
    p1 := head
    p2 := secondHalfStart
    result := true
    for result && p2 != nil {
        if p1.Val != p2.Val {
            result = false
        }
        p1 = p1.Next
        p2 = p2.Next
    }

    // 还原链表并返回结果
    firstHalfEnd.Next = reverseList(secondHalfStart)
    return result
}

【141】环形链表

// 判断是否有环
func hasCycle(head *ListNode) bool {
	fast := head
	slow := head
	for slow != nil && fast != nil && fast.Next != nil {
		fast = fast.Next.Next
		slow = slow.Next
		if fast == slow {
			return true
		}
	}
	return false
}


【142】环形链表II

// 判断环的起点

func detectCycle(head *ListNode) *ListNode {
	if head == nil {
		return nil
	}

	fast, slow := head, head

	for fast != nil && fast.Next != nil {
		fast = head.Next.Next
		slow = head.Next
		if fast == slow {
			fast = head
			for fast != slow {
				fast = fast.Next
				slow = slow.Next
			}
			return slow
		}
	}
	return nil
}

【160】相交链表

func getIntersectionNode(headA, headB *ListNode) *ListNode {
    if headA == nil || headB == nil {
        return nil
    }

    a := headA
    b := headB

    for a != b {
        if a == nil {
            a = headB
        } else {
            a = a.Next
        }

        if b == nil {
            b = headA
        } else {
            b = b.Next
        }
    }
    return a
}

【21】合并两个有序链表

func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
    if l1 == nil {
        return l2
    }
    if l2 == nil {
	return l1
    }
    if l1.Val < l2.Val {
        l1.Next = mergeTwoLists(l1.Next, l2)
	return l1
    } else {
        l2.Next = mergeTwoLists(l1, l2.Next)
	return l2
    }
}

【328】奇偶链表

func oddEvenList(head *ListNode) *ListNode {
    oddNode := &ListNode{Val: -1}
    evenNode := &ListNode{Val: -1}

    p1, p2 := oddNode, evenNode

    // 奇偶分别放到两个链表中
    count := 0
    for cur := head; cur != nil; cur = cur.Next {
        count++
        if count % 2 == 1 {
            p1.Next = cur
            p1 = p1.Next
        } else {
            p2.Next = cur
            p2 = p2.Next 
        }
    }

    // 拼接
    p1.Next = evenNode.Next
    p2.Next = nil
    return oddNode.Next
}

【203】删除链表元素

func removeElements(head *ListNode, val int) *ListNode {
    if head == nil {
        return head
    }

    new := &ListNode{Val: 0, Next: head}
    cur := head
    pre := new
    for cur != nil {
        if cur.Val == val {
            pre.Next = cur.Next
        } else {
            pre = cur
        }
        cur = cur.Next
    }
    return new.Next
}