
这份文档不是讲完整题解而是把开发岗 60 题里最常用的代码模板按语言整理出来。目标只有一个面试时别在基础写法上浪费时间。使用方式先熟悉你自己的主语言模板再把同题型模板写到能脱稿面试前只复习这些高频骨架一、数组 / 哈希1. 两数之和JavaMapInteger, Integer map new HashMap(); for (int i 0; i nums.length; i) { int need target - nums[i]; if (map.containsKey(need)) { return new int[]{map.get(need), i}; } map.put(nums[i], i); } return new int[0];Cunordered_mapint, int mp; for (int i 0; i nums.size(); i) { int need target - nums[i]; if (mp.count(need)) return {mp[need], i}; mp[nums[i]] i; } return {};Gomp : map[int]int{} for i, v : range nums { need : target - v if j, ok : mp[need]; ok { return []int{j, i} } mp[v] i } return nilPythonmp {} for i, v in enumerate(nums): need target - v if need in mp: return [mp[need], i] mp[v] i return []2. 前缀和模板Javaint[] pre new int[n 1]; for (int i 0; i n; i) { pre[i 1] pre[i] nums[i]; } int sum pre[r 1] - pre[l];Cvectorint pre(n 1, 0); for (int i 0; i n; i) pre[i 1] pre[i] nums[i]; int sum pre[r 1] - pre[l];Gopre : make([]int, n1) for i : 0; i n; i { pre[i1] pre[i] nums[i] } sum : pre[r1] - pre[l]Pythonpre [0] * (n 1) for i in range(n): pre[i 1] pre[i] nums[i] sum_ pre[r 1] - pre[l]校招大礼包获取入口可能是至今最全最好最实用的校招大礼包减少信息差预期漫步无敌的刷提不如有的放矢针对性的准备这样才能有效备考有了这份资料不说100%拿到offer至少帮你提升50%概率拿到offer二、双指针 / 滑动窗口3. 无重复字符的最长子串模板JavaMapCharacter, Integer map new HashMap(); int left 0, ans 0; for (int right 0; right s.length(); right) { char c s.charAt(right); if (map.containsKey(c)) { left Math.max(left, map.get(c) 1); } map.put(c, right); ans Math.max(ans, right - left 1); } return ans;Cunordered_mapchar, int mp; int left 0, ans 0; for (int right 0; right s.size(); right) { char c s[right]; if (mp.count(c)) left max(left, mp[c] 1); mp[c] right; ans max(ans, right - left 1); } return ans;Gomp : map[byte]int{} left, ans : 0, 0 for right : 0; right len(s); right { c : s[right] if idx, ok : mp[c]; ok idx left { left idx 1 } mp[c] right if right-left1 ans { ans right - left 1 } } return ansPythonmp {} left ans 0 for right, c in enumerate(s): if c in mp and mp[c] left: left mp[c] 1 mp[c] right ans max(ans, right - left 1) return ans4. 滑动窗口最大值 单调队列模板JavaDequeInteger deque new ArrayDeque(); for (int i 0; i nums.length; i) { while (!deque.isEmpty() deque.peekFirst() i - k) deque.pollFirst(); while (!deque.isEmpty() nums[deque.peekLast()] nums[i]) deque.pollLast(); deque.offerLast(i); if (i k - 1) ans.add(nums[deque.peekFirst()]); }Cdequeint dq; for (int i 0; i nums.size(); i) { while (!dq.empty() dq.front() i - k) dq.pop_front(); while (!dq.empty() nums[dq.back()] nums[i]) dq.pop_back(); dq.push_back(i); if (i k - 1) ans.push_back(nums[dq.front()]); }Godq : []int{} for i : 0; i len(nums); i { if len(dq) 0 dq[0] i-k { dq dq[1:] } for len(dq) 0 nums[dq[len(dq)-1]] nums[i] { dq dq[:len(dq)-1] } dq append(dq, i) if i k-1 { ans append(ans, nums[dq[0]]) } }Pythonfrom collections import deque dq deque() for i, v in enumerate(nums): while dq and dq[0] i - k: dq.popleft() while dq and nums[dq[-1]] v: dq.pop() dq.append(i) if i k - 1: ans.append(nums[dq[0]])三、链表5. 反转链表模板JavaListNode prev null, cur head; while (cur ! null) { ListNode next cur.next; cur.next prev; prev cur; cur next; } return prev;CListNode* prev nullptr; ListNode* cur head; while (cur) { ListNode* next cur-next; cur-next prev; prev cur; cur next; } return prev;Govar prev *ListNode cur : head for cur ! nil { next : cur.Next cur.Next prev prev cur cur next } return prevPythonprev, cur None, head while cur: nxt cur.next cur.next prev prev cur cur nxt return prev6. 快慢指针找环 / 中点模板JavaListNode slow head, fast head; while (fast ! null fast.next ! null) { slow slow.next; fast fast.next.next; if (slow fast) return true; } return false;CListNode *slow head, *fast head; while (fast fast-next) { slow slow-next; fast fast-next-next; if (slow fast) return true; } return false;Goslow, fast : head, head for fast ! nil fast.Next ! nil { slow slow.Next fast fast.Next.Next if slow fast { return true } } return falsePythonslow fast head while fast and fast.next: slow slow.next fast fast.next.next if slow fast: return True return False四、栈 / 堆7. 单调栈模板JavaDequeInteger stack new ArrayDeque(); for (int i 0; i n; i) { while (!stack.isEmpty() nums[stack.peek()] nums[i]) { int idx stack.pop(); } stack.push(i); }Cstackint st; for (int i 0; i n; i) { while (!st.empty() nums[st.top()] nums[i]) { int idx st.top(); st.pop(); } st.push(i); }Gost : []int{} for i : 0; i n; i { for len(st) 0 nums[st[len(st)-1]] nums[i] { idx : st[len(st)-1] _ idx st st[:len(st)-1] } st append(st, i) }Pythonst [] for i, v in enumerate(nums): while st and nums[st[-1]] v: idx st.pop() st.append(i)8. Top K 小顶堆模板JavaPriorityQueueInteger pq new PriorityQueue(); for (int x : nums) { pq.offer(x); if (pq.size() k) pq.poll(); } return pq.peek();Cpriority_queueint, vectorint, greaterint pq; for (int x : nums) { pq.push(x); if (pq.size() k) pq.pop(); } return pq.top();Gotype MinHeap []int func (h MinHeap) Len() int { return len(h) } func (h MinHeap) Less(i, j int) bool { return h[i] h[j] } func (h MinHeap) Swap(i, j int) { h[i], h[j] h[j], h[i] } func (h *MinHeap) Push(x interface{}) { *h append(*h, x.(int)) } func (h *MinHeap) Pop() interface{} { old : *h x : old[len(old)-1] *h old[:len(old)-1] return x }Pythonimport heapq hp [] for x in nums: heapq.heappush(hp, x) if len(hp) k: heapq.heappop(hp) return hp[0]五、二分查找9. 标准二分模板Javaint left 0, right nums.length - 1; while (left right) { int mid left (right - left) / 2; if (nums[mid] target) return mid; if (nums[mid] target) left mid 1; else right mid - 1; } return -1;Cint left 0, right nums.size() - 1; while (left right) { int mid left (right - left) / 2; if (nums[mid] target) return mid; if (nums[mid] target) left mid 1; else right mid - 1; } return -1;Goleft, right : 0, len(nums)-1 for left right { mid : left (right-left)/2 if nums[mid] target { return mid } if nums[mid] target { left mid 1 } else { right mid - 1 } } return -1Pythonleft, right 0, len(nums) - 1 while left right: mid left (right - left) // 2 if nums[mid] target: return mid if nums[mid] target: left mid 1 else: right mid - 1 return -110. 左边界模板Javaint left 0, right nums.length; while (left right) { int mid left (right - left) / 2; if (nums[mid] target) right mid; else left mid 1; } return left;Cint left 0, right nums.size(); while (left right) { int mid left (right - left) / 2; if (nums[mid] target) right mid; else left mid 1; } return left;Goleft, right : 0, len(nums) for left right { mid : left (right-left)/2 if nums[mid] target { right mid } else { left mid 1 } } return leftPythonleft, right 0, len(nums) while left right: mid left (right - left) // 2 if nums[mid] target: right mid else: left mid 1 return left六、二叉树11. DFS 递归模板Javavoid dfs(TreeNode root) { if (root null) return; dfs(root.left); dfs(root.right); }Cvoid dfs(TreeNode* root) { if (!root) return; dfs(root-left); dfs(root-right); }Gofunc dfs(root *TreeNode) { if root nil { return } dfs(root.Left) dfs(root.Right) }Pythondef dfs(root): if not root: return dfs(root.left) dfs(root.right)12. BFS 层序遍历模板JavaQueueTreeNode queue new LinkedList(); queue.offer(root); while (!queue.isEmpty()) { int size queue.size(); for (int i 0; i size; i) { TreeNode node queue.poll(); if (node.left ! null) queue.offer(node.left); if (node.right ! null) queue.offer(node.right); } }CqueueTreeNode* q; q.push(root); while (!q.empty()) { int size q.size(); while (size--) { auto node q.front(); q.pop(); if (node-left) q.push(node-left); if (node-right) q.push(node-right); } }Goq : []*TreeNode{root} for len(q) 0 { size : len(q) for i : 0; i size; i { node : q[0] q q[1:] if node.Left ! nil { q append(q, node.Left) } if node.Right ! nil { q append(q, node.Right) } } }Pythonfrom collections import deque q deque([root]) while q: for _ in range(len(q)): node q.popleft() if node.left: q.append(node.left) if node.right: q.append(node.right)13. 最近公共祖先模板JavaTreeNode lca(TreeNode root, TreeNode p, TreeNode q) { if (root null || root p || root q) return root; TreeNode left lca(root.left, p, q); TreeNode right lca(root.right, p, q); if (left ! null right ! null) return root; return left ! null ? left : right; }CTreeNode* lca(TreeNode* root, TreeNode* p, TreeNode* q) { if (!root || root p || root q) return root; TreeNode* left lca(root-left, p, q); TreeNode* right lca(root-right, p, q); if (left right) return root; return left ? left : right; }Gofunc lca(root, p, q *TreeNode) *TreeNode { if root nil || root p || root q { return root } left : lca(root.Left, p, q) right : lca(root.Right, p, q) if left ! nil right ! nil { return root } if left ! nil { return left } return right }Pythondef lca(root, p, q): if not root or root p or root q: return root left lca(root.left, p, q) right lca(root.right, p, q) if left and right: return root return left or right七、回溯14. 全排列模板Javavoid backtrack(ListInteger path, boolean[] used) { if (path.size() nums.length) { ans.add(new ArrayList(path)); return; } for (int i 0; i nums.length; i) { if (used[i]) continue; used[i] true; path.add(nums[i]); backtrack(path, used); path.remove(path.size() - 1); used[i] false; } }Cvoid dfs(vectorint path, vectorint used) { if (path.size() nums.size()) { ans.push_back(path); return; } for (int i 0; i nums.size(); i) { if (used[i]) continue; used[i] 1; path.push_back(nums[i]); dfs(path, used); path.pop_back(); used[i] 0; } }Govar dfs func() dfs func() { if len(path) len(nums) { tmp : append([]int{}, path...) ans append(ans, tmp) return } for i : 0; i len(nums); i { if used[i] { continue } used[i] true path append(path, nums[i]) dfs() path path[:len(path)-1] used[i] false } }Pythondef dfs(): if len(path) len(nums): ans.append(path[:]) return for i in range(len(nums)): if used[i]: continue used[i] True path.append(nums[i]) dfs() path.pop() used[i] False八、动态规划15. 一维 DP 模板Javaint[] dp new int[n 1]; dp[0] 0; for (int i 1; i n; i) { dp[i] ...; } return dp[n];Cvectorint dp(n 1, 0); for (int i 1; i n; i) { dp[i] ...; } return dp[n];Godp : make([]int, n1) for i : 1; i n; i { dp[i] 0 } return dp[n]Pythondp [0] * (n 1) for i in range(1, n 1): dp[i] 0 return dp[n]16. 最长公共子序列 二维 DP 模板Javaint m text1.length(), n text2.length(); int[][] dp new int[m 1][n 1]; for (int i 1; i m; i) { for (int j 1; j n; j) { if (text1.charAt(i - 1) text2.charAt(j - 1)) { dp[i][j] dp[i - 1][j - 1] 1; } else { dp[i][j] Math.max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[m][n];Cint m text1.size(), n text2.size(); vectorvectorint dp(m 1, vectorint(n 1, 0)); for (int i 1; i m; i) { for (int j 1; j n; j) { if (text1[i - 1] text2[j - 1]) dp[i][j] dp[i - 1][j - 1] 1; else dp[i][j] max(dp[i - 1][j], dp[i][j - 1]); } } return dp[m][n];Gom, n : len(text1), len(text2) dp : make([][]int, m1) for i : range dp { dp[i] make([]int, n1) } for i : 1; i m; i { for j : 1; j n; j { if text1[i-1] text2[j-1] { dp[i][j] dp[i-1][j-1] 1 } else if dp[i-1][j] dp[i][j-1] { dp[i][j] dp[i-1][j] } else { dp[i][j] dp[i][j-1] } } } return dp[m][n]Pythonm, n len(text1), len(text2) dp [[0] * (n 1) for _ in range(m 1)] for i in range(1, m 1): for j in range(1, n 1): if text1[i - 1] text2[j - 1]: dp[i][j] dp[i - 1][j - 1] 1 else: dp[i][j] max(dp[i - 1][j], dp[i][j - 1]) return dp[m][n]九、开发岗最该背熟的模板如果时间有限只背下面这些哈希表查找前缀和滑动窗口单调队列反转链表快慢指针单调栈堆 Top K二分查找DFS / BFS回溯模板一维 DP / 二维 DP十、面试时最容易写挂的点JavaList和数组互转不熟PriorityQueue默认小顶堆Deque的push/pop/peek和offer/poll/peek混用Cunordered_map和map混淆priority_queue默认大顶堆指针判空和引用使用不稳Go切片扩容和截断容易写错heap.Interface不熟map 默认零值逻辑容易漏Python列表浅拷贝写错递归回溯忘记path[:]heapq只有小顶堆十一、复习建议不要试图背 60 道题的完整代码要背的是“题型骨架”同类题共用一套模板速度会快很多面试前至少手写一遍滑动窗口链表翻转二叉树遍历回溯DP如果你只能准备一门语言就把你的主语言模板练到闭眼能写。