Golang 算法与数据结构:Go 实现的常见题型与解法

2次阅读

go实现算法需紧扣切片动态特性、map零值陷阱、结构体树节点与后序递归、bfs切片队列等原生机制,强调原地操作、o(1)查找及简洁组合。

Golang 算法与数据结构:Go 实现的常见题型与解法

Go 语言实现算法与数据结构,核心在于理解标准库支持、内存模型特性(如切片底层数组共享)、以及 Go 风格的简洁表达——不依赖复杂类封装,多用函数式组合、结构体+方法、通道协程等原生能力解决问题。

数组与切片:动态扩容与原地操作是关键

Go 没有传统意义上的“数组题”,几乎所有题目都落在 []int 等切片上。要注意 append 可能触发底层数组复制,而双指针原地修改(如移除元素、快排分区)能避免额外空间开销。

  • 删除重复元素(有序):用单指针记录已处理位置,跳过相同值,最后切片截断 —— 时间 O(n),空间 O(1)
  • 两数之和 II(有序数组):左右双指针向中间收缩,比哈希表更省内存,且符合 Go 的迭代习惯
  • 旋转数组(如 [1,2,3,4,5] → [4,5,1,2,3]):三次反转法(整体 + 前段 + 后段),无需额外切片分配

哈希表:map 是主力,但要注意零值陷阱

map[int]intmap[String]bool 覆盖绝大多数查找/计数场景。但需警惕:访问不存在键返回零值(0、””、false),不能直接判断是否“存在”。应使用双赋值语法 v, ok := m[key]

  • 字母异位词分组:以排序后字符串或字符频次数组(用 [26]int 作 map 键)为 key,value 是字符串切片
  • 子数组和为 K:前缀和 + map 记录每个和首次出现位置,利用 Go 的 map 查找 O(1) 特性
  • LRU 缓存:用 map[key]*list.Element + container/list 实现 O(1) 查找与移动,避免手写双向链表

树与递归:用结构体定义节点,优先考虑后序遍历

Go 中树节点通常定义为:

type TreeNode struct {     Val   int     Left  *TreeNode     Right *TreeNode }

空节点即 nil,递归终止条件清晰。后序遍历天然适合“自底向上”问题(如最大路径和、平衡判断、最近公共祖先)。

  • 二叉树最大深度:递归返回左右子树深度最大值 + 1;非递归可用层序 BFS(queue []*TreeNode
  • 翻转二叉树:递归交换左右指针,一行核心逻辑:root.Left, root.Right = invertTree(root.Right), invertTree(root.Left)
  • 二叉搜索树中第 K 小:中序遍历(左→根→右)天然升序,可配合闭包计数提前退出,避免全遍历

图与搜索:BFS 用切片模拟队列,DFS 偏爱递归+visited map

图常以邻接表形式给出:map[int][]int[][]int。Go 没有内置队列/,但切片 append 和切片截断(q = q[1:])足够高效做 BFS;DFS 多用递归+闭包或显式栈。

  • 岛屿数量(DFS):遍历网格,遇 ‘1’ 则递归沉没(设为 ‘0’)四周连通陆地,避免额外 visited 空间
  • 课程表(拓扑排序):统计入度 + BFS(Kahn 算法),用 queue []int 存入度为 0 的课,每次出队更新邻接点入度
  • 单词接龙(BFS 最短路径):每层枚举当前单词所有可能变换(26×位置),用 map 记录已访问,避免重复入队

text=ZqhQzanResources