# 学习 **Repository Path**: hao-momo/learn ## Basic Information - **Project Name**: 学习 - **Description**: No description available - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-12-24 - **Last Updated**: 2026-02-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 日常 记录我大学之后的学习,证明我还活着 ## 学习: 2025.11.25 今年尽力了很多,做了很多项目,也认识了很多人,也是经历很多起起伏伏。大学毕业以前,总觉得自己很出色,想要什么自己应该都能做到。其实后面也都知道,一切都是最好的安排。 现在也是想了很多。自己想做到自己心里的自己,然后呢?我是否也应该做点什么去让自己认同起来,我会逐步把自己这段时间学的东西总结一下,争取每天做点东西,学点东西。真的真的, 我很想做到自己心里的自己。 # 目录 # 笔记 ## [网络IO模型](https://gitee.com/hao-momo/daily/blob/master/note/go/src/网络IO模型.md) # leetcode # 单链表 ## [21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/) 1. 创建一个虚拟的头节点 2. 然后一次遍历每个链表,双指针 3. 将小节点添加到这个新的链表。 ```go func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode { res := &ListNode{} p := res for list1 != nil && list2 != nil { if list1.Val < list2.Val { p.Next = list1 list1 = list1.Next } else { p.Next = list2 list2 = list2.Next } p = p.Next } if list1 != nil { p.Next = list1 } if list2 != nil { p.Next = list2 } return res.Next } ``` ## [86. 分隔链表](https://leetcode.cn/problems/partition-list/) 1. 将要构造的链表变成两部分,左边都是比他小,右边都是比他大于等于 2. 最后连起来就行 ```go func partition(head *ListNode, x int) *ListNode { res := &ListNode{} left := res tmp := &ListNode{} right := tmp for head != nil { if head.Val < x { left.Next = head left = left.Next } else { right.Next = head right = right.Next } head = head.Next } right.Next = nil left.Next = tmp.Next return res.Next } ``` ## [23. 合并 K 个升序链表](https://leetcode.cn/problems/merge-k-sorted-lists/) 合并2个链表类似,但是这里用最小堆去获得一组链表中最小的节点,然后依次加入到虚拟链表 ```go func mergeKLists(lists []*ListNode) *ListNode { heap := &MinHeap{data: make([]*ListNode, 0, len(lists)), size: 0} res := &ListNode{} p := res for _, list := range lists { if list != nil { heap.Insert(list) } } for heap.size > 0 { minNode, _ := heap.ExtractMin() p.Next = minNode p = p.Next if minNode.Next != nil { heap.Insert(minNode.Next) } } return res.Next } type MinHeap struct { data []*ListNode size int } func (h *MinHeap) siftUp(i int) { for i > 0 { parent := (i - 1) / 2 if h.data[parent] == nil || h.data[i] == nil { break } if h.data[i].Val < h.data[parent].Val { h.data[i], h.data[parent] = h.data[parent], h.data[i] i = parent } else { break } } } func (h *MinHeap) siftDown(i int) { for { minIndex := i left := 2*i + 1 right := 2*i + 2 if left < h.size && h.data[left] != nil && h.data[minIndex] != nil && h.data[left].Val < h.data[minIndex].Val { minIndex = left } if right < h.size && h.data[right] != nil && h.data[minIndex] != nil && h.data[right].Val < h.data[minIndex].Val { minIndex = right } if minIndex == i { break } h.data[i], h.data[minIndex] = h.data[minIndex], h.data[i] i = minIndex } } func (h *MinHeap) Insert(val *ListNode) { if val == nil { return } if h.size >= len(h.data) { newSize := len(h.data) * 2 if newSize == 0 { newSize = 1 } newData := make([]*ListNode, newSize) copy(newData, h.data) h.data = newData } h.data[h.size] = val h.size++ h.siftUp(h.size - 1) } ``` ## [19. 删除链表的倒数第 N 个结点](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/) 1. 一个指针先走n步 2. 再有一个虚拟节点的指针走走到第一个指针到末尾,那这个指针的下个指针就是要删除的第N个节点 ``` func removeNthFromEnd(head *ListNode, n int) *ListNode { dummy := &ListNode{Next: head} p1 := head for i := 0; i < n; i++ { p1 = p1.Next } p2 := dummy for p1 != nil { p1 = p1.Next p2 = p2.Next } p2.Next = p2.Next.Next return dummy.Next } ``` ## [876. 链表的中间结点](https://leetcode.cn/problems/middle-of-the-linked-list/) 一个指针走一步,一个走两步,两步走到末尾另外一个就在中点 ```go func middleNode(head *ListNode) *ListNode { p1 := head p2 := head for p1 != nil && p1.Next != nil { p1 = p1.Next.Next p2 = p2.Next } return p2 } ``` ## [142. 环形链表 II](https://leetcode.cn/problems/linked-list-cycle-ii/) 先快走2步慢走一步,相遇之后,慢的再重头开始走,再相遇就是环的起点。(数学证明) ```go func detectCycle(head *ListNode) *ListNode { p1 := head p2 := head b := false for p1 != nil && p1.Next != nil { p1 = p1.Next.Next p2 = p2.Next if p1 == p2 { b = true break } } if !b { return nil } p2 = head for p1 != p2 { p1 = p1.Next p2 = p2.Next } return p2 } ``` ## [160. 相交链表](https://leetcode.cn/problems/intersection-of-two-linked-lists/) 双指针一步一步走,先走完的走从另外一个开始相遇就是有交点 ```go func getIntersectionNode(p1, p2 *ListNode) *ListNode { c1, c2 := p1, p2 for c1 != c2 { if c1 == nil { c1 = p2 } else { c1 = c1.Next } if c2 == nil { c2 = p1 } else { c2 = c2.Next } } return c1 } ``` # 数据结构 ## 小顶堆 ```go type MinHeap struct { data []int size int } // 上浮:调整插入节点 func (m *MinHeap) siftUp(i int) { if i == 0 { return } parent := (i - 1) / 2 if m.data[i] < m.data[parent] { // 移除多余的 i < m.size 检查 m.data[i], m.data[parent] = m.data[parent], m.data[i] m.siftUp(parent) } } // 下沉:调整根节点 func (m *MinHeap) siftDown(i int) { left := 2*i + 1 right := 2*i + 2 minIndex := i if left < m.size && m.data[left] < m.data[minIndex] { minIndex = left } if right < m.size && m.data[right] < m.data[minIndex] { minIndex = right } if minIndex == i { return } m.data[i], m.data[minIndex] = m.data[minIndex], m.data[i] m.siftDown(minIndex) } // 入堆 func (m *MinHeap) push(v int) { if m.size == len(m.data) { // 初始扩容处理 newCap := len(m.data) * 2 if newCap == 0 { newCap = 4 } n := make([]int, newCap) copy(n, m.data) m.data = n } m.data[m.size] = v m.size++ m.siftUp(m.size - 1) } // 出堆 - 修复关键bug func (m *MinHeap) pop() int { if m.size == 0 { return -1 // 或用 (int, bool) 模式 } res := m.data[0] m.data[0] = m.data[m.size-1] m.size-- if m.size > 0 { // 避免空堆时调用 m.siftDown(0) } return res } ```