大厂校招必刷60 题 Java / C++ / Go / Python解法

📅 2026/7/9 5:05:22 👁️ 阅读次数 📝 编程学习
大厂校招必刷60 题 Java / C++ / Go / Python解法

这份文档不是讲完整题解,而是把开发岗 60 题里最常用的代码模板按语言整理出来。
目标只有一个:面试时别在基础写法上浪费时间。

使用方式:

  • 先熟悉你自己的主语言模板

  • 再把同题型模板写到能脱稿

  • 面试前只复习这些高频骨架


一、数组 / 哈希

1. 两数之和

Java
Map<Integer, 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];
C++
unordered_map<int, 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 {};
Go
mp := 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 nil
Python
mp = {} for i, v in enumerate(nums): need = target - v if need in mp: return [mp[need], i] mp[v] = i return []

2. 前缀和模板

Java
int[] 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];
C++
vector<int> 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];
Go
pre := make([]int, n+1) for i := 0; i < n; i++ { pre[i+1] = pre[i] + nums[i] } sum := pre[r+1] - pre[l]
Python
pre = [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. 无重复字符的最长子串模板

Java
Map<Character, 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;
C++
unordered_map<char, 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;
Go
mp := 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-left+1 > ans { ans = right - left + 1 } } return ans
Python
mp = {} 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 ans

4. 滑动窗口最大值 单调队列模板

Java
Deque<Integer> 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()]); }
C++
deque<int> 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()]); }
Go
dq := []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]]) } }
Python
from 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. 反转链表模板

Java
ListNode prev = null, cur = head; while (cur != null) { ListNode next = cur.next; cur.next = prev; prev = cur; cur = next; } return prev;
C++
ListNode* prev = nullptr; ListNode* cur = head; while (cur) { ListNode* next = cur->next; cur->next = prev; prev = cur; cur = next; } return prev;
Go
var prev *ListNode cur := head for cur != nil { next := cur.Next cur.Next = prev prev = cur cur = next } return prev
Python
prev, cur = None, head while cur: nxt = cur.next cur.next = prev prev = cur cur = nxt return prev

6. 快慢指针找环 / 中点模板

Java
ListNode slow = head, fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) return true; } return false;
C++
ListNode *slow = head, *fast = head; while (fast && fast->next) { slow = slow->next; fast = fast->next->next; if (slow == fast) return true; } return false;
Go
slow, fast := head, head for fast != nil && fast.Next != nil { slow = slow.Next fast = fast.Next.Next if slow == fast { return true } } return false
Python
slow = fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: return True return False

四、栈 / 堆

7. 单调栈模板

Java
Deque<Integer> 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); }
C++
stack<int> 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); }
Go
st := []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) }
Python
st = [] for i, v in enumerate(nums): while st and nums[st[-1]] < v: idx = st.pop() st.append(i)

8. Top K 小顶堆模板

Java
PriorityQueue<Integer> pq = new PriorityQueue<>(); for (int x : nums) { pq.offer(x); if (pq.size() > k) pq.poll(); } return pq.peek();
C++
priority_queue<int, vector<int>, greater<int>> pq; for (int x : nums) { pq.push(x); if (pq.size() > k) pq.pop(); } return pq.top();
Go
type 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 }
Python
import heapq hp = [] for x in nums: heapq.heappush(hp, x) if len(hp) > k: heapq.heappop(hp) return hp[0]

五、二分查找

9. 标准二分模板

Java
int 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;
C++
int 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;
Go
left, 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 -1
Python
left, 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 -1

10. 左边界模板

Java
int 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;
C++
int 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;
Go
left, right := 0, len(nums) for left < right { mid := left + (right-left)/2 if nums[mid] >= target { right = mid } else { left = mid + 1 } } return left
Python
left, 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 递归模板

Java
void dfs(TreeNode root) { if (root == null) return; dfs(root.left); dfs(root.right); }
C++
void dfs(TreeNode* root) { if (!root) return; dfs(root->left); dfs(root->right); }
Go
func dfs(root *TreeNode) { if root == nil { return } dfs(root.Left) dfs(root.Right) }
Python
def dfs(root): if not root: return dfs(root.left) dfs(root.right)

12. BFS 层序遍历模板

Java
Queue<TreeNode> 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); } }
C++
queue<TreeNode*> 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); } }
Go
q := []*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) } } }
Python
from 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. 最近公共祖先模板

Java
TreeNode 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; }
C++
TreeNode* 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; }
Go
func 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 }
Python
def 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. 全排列模板

Java
void backtrack(List<Integer> 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; } }
C++
void dfs(vector<int>& path, vector<int>& 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; } }
Go
var 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 } }
Python
def 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 模板

Java
int[] dp = new int[n + 1]; dp[0] = 0; for (int i = 1; i <= n; i++) { dp[i] = ...; } return dp[n];
C++
vector<int> dp(n + 1, 0); for (int i = 1; i <= n; i++) { dp[i] = ...; } return dp[n];
Go
dp := make([]int, n+1) for i := 1; i <= n; i++ { dp[i] = 0 } return dp[n]
Python
dp = [0] * (n + 1) for i in range(1, n + 1): dp[i] = 0 return dp[n]

16. 最长公共子序列 二维 DP 模板

Java
int 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];
C++
int m = text1.size(), n = text2.size(); vector<vector<int>> dp(m + 1, vector<int>(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];
Go
m, n := len(text1), len(text2) dp := make([][]int, m+1) for i := range dp { dp[i] = make([]int, n+1) } 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]
Python
m, 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]

九、开发岗最该背熟的模板

如果时间有限,只背下面这些:

  1. 哈希表查找

  2. 前缀和

  3. 滑动窗口

  4. 单调队列

  5. 反转链表

  6. 快慢指针

  7. 单调栈

  8. 堆 Top K

  9. 二分查找

  10. DFS / BFS

  11. 回溯模板

  12. 一维 DP / 二维 DP


十、面试时最容易写挂的点

Java

  • List和数组互转不熟

  • PriorityQueue默认小顶堆

  • Dequepush/pop/peekoffer/poll/peek混用

C++

  • unordered_mapmap混淆

  • priority_queue默认大顶堆

  • 指针判空和引用使用不稳

Go

  • 切片扩容和截断容易写错

  • heap.Interface不熟

  • map 默认零值逻辑容易漏

Python

  • 列表浅拷贝写错

  • 递归回溯忘记path[:]

  • heapq只有小顶堆


十一、复习建议

  • 不要试图背 60 道题的完整代码

  • 要背的是“题型骨架”

  • 同类题共用一套模板,速度会快很多

  • 面试前至少手写一遍:
    • 滑动窗口

    • 链表翻转

    • 二叉树遍历

    • 回溯

    • DP

如果你只能准备一门语言,就把你的主语言模板练到闭眼能写。