二叉树层序遍历需先记录当前层长度l := len(queue),再用for i := 0; i < l循环处理,避免range queue导致混入下层节点;同时注意nil输入、循环退出及切片越界等边界问题。
Go 语言手撕算法面试,不靠背题,靠对数据结构行为和边界条件的即时反应。你写出来的代码,面试官第一眼会看三件事:是否处理
或空输入、循环/递归是否真能退出、切片/指针操作有没有越界或共享底层数组的隐性 bug。
二叉树层序遍历:别直接写 for range queue
很多人一上来就用
,这是错的——Go 的 range 是对当前切片副本迭代,而你在循环中不断往
尾部追加新节点,会导致遍历“本层”时混入下一层节点。
正确做法是先记下当前层长度:
用
锁定本轮要处理的节点数
内层用
取并切片
必须提前返回,否则后续
会 panic
快排 partition 过程:别用中间索引当 pivot 就完事
取
看似稳妥,但若数组已有序或大量重复值,会导致极端不平衡划分,递归深度爆炸——面试官会追问“最坏时间复杂度多少”。
立即学习
“
go语言免费学习笔记(深入)
”;
更鲁棒的做法:
随机选一个索引:
,再 swap 到末尾
或者用三数取中(
、
、
中位数)
partition 循环里必须保证
LRU 缓存:别直接用 map[int]int 存 value
面试要求的是“最近最少使用”,意味着你要能 O(1) 移动某个 key 到头部、O(1) 删除尾部。只用哈希表做不到移动位置。
必须组合两个结构:
哈希表:
,存 key → 链表节点指针
双向链表:
,节点值是自定义结构体(如
)
每次
后调用
,不是重建节点;
时先查 map,存在就复用节点、只更新 value
漏掉
这一步,Put 更新值就失效了。
切片扩容陷阱:make([]int, 0, n) 不是可选优化项
手撕 BFS、DFS 路径收集这类题,常要反复
。如果初始没设容量,比如
,遇到深路径时频繁扩容会触发多次底层数组复制,性能断崖下跌,且容易在调试时误判逻辑错误。
安全做法:
预估最大长度(如二叉树高度、图节点数),用
若无法预估,至少在递归函数参数里传入预分配的切片,避免闭包捕获导致意外共享底层数组
检查
不是必须的——Go 的
自动处理,但你知道它会发生,才能解释清楚空间复杂度
真正容易被忽略的,是切片截取后仍指向原数组——比如在 DFS 回溯中写
没问题,但若之前做过
才安全;否则多个递归分支可能踩同一块内存。
nilfor _, node := range queuequeuel := len(queue)for i := 0; i ,每次从 queue[0]queue = queue[1:]root == nilnode.Leftpivot := nums[(low + high) / 2]rand.Intn(high - low + 1) + lownums[low]nums[mid]nums[high]left ,否则交换后可能越界map[int]*list.Element*list.List&Pair{key, value}GetMoveToFrontPutelem.Value.(*Pair).value = valueappendpath := []int{}make([]int, 0, maxDepth)len(path) == cap(path)appendpath = path[:len(path)-1]copy(newPath, path)