面试季来了!这5道高频算法题,今年秋天你必须要会。
为什么是这10道题?
2026年的技术面试已经和几年前大不相同:
•AI工具普及:面试官知道你会用ChatGPT,所以题目更灵活。
•更注重实际应用:不再是纯算法,而是结合真实场景。
•沟通权重增加:要能说清楚你的思路。
•时间压力更大:要在有限时间内展示能力。
我精选了这10道题,因为它们:
✓覆盖面广:数组、字符串、树、图、动态规划。
✓频率极高:2026年各大公司面试真题。
✓难度适中:不是最难的,但一定要会。
✓有扩展性:每道题都能引申出更多变种。
问题1:两数之和(Two Sum)
经典版本:
给定一个整数数组和目标值,找出数组中和为目标值的两个数的索引。示例:
输入: nums = [2, 7, 11, 15], target = 9 输出: [0, 1] 解释: nums[0] + nums[1] = 2 + 7 = 92026年进阶问题:
面试官不再满足于看到你能写出O(n)的哈希表解法。他们会追问:
追问1:如果有多个答案怎么办?
def two_sum_all_pairs(nums, target): """ 返回所有满足条件的数对 """ seen = {} result = [] for i, num in enumerate(nums): complement = target - num if complement in seen: # 找到所有之前的匹配 for j in seen[complement]: result.append([j, i]) if num not in seen: seen[num] = [] seen[num].append(i) return result追问2:如果数组已经排序了呢?
def two_sum_sorted(nums, target): """ 排序数组版本 - 使用双指针 时间复杂度:O(n) 空间复杂度:O(1) """ left, right = 0, len(nums) - 1 while left < right: current_sum = nums[left] + nums[right] if current_sum == target: return [left, right] elif current_sum < target: left += 1 else: right -= 1 return [] # 没找到追问3:如果要求返回的是数值而不是索引?
这时候就不需要哈希表了,直接用双指针即可(即使数组未排序,也可以先排序再双指针,但要注意记录原始索引)。
关键考点:
2026年加分项:
✓ 主动讨论不同解法的 trade-off;
✓ 提问澄清需求(是否有重复?是否有序?返回什么?);
✓ 写出 clean、有注释的代码;
✓ 考虑错误处理和边界情况。
问题2:有效的括号(Valid Parentheses)
题目描述:
给定一个只包括 '('、')'、'{'、'}'、'['、']' 的字符串,判断字符串是否有效。有效字符串需满足:
1. 左括号必须用相同类型的右括号闭合
2. 左括号必须以正确的顺序闭合
示例:
输入: "()[]{}" → 输出: true 输入: "([)]" → 输出: false 输入: "{[]}" → 输出: true标准解法:栈(Stack)
def is_valid(s: str) -> bool: """ 使用栈来匹配括号 时间复杂度:O(n) 空间复杂度:O(n) """ stack = [] mapping = {')': '(', '}': '{', ']': '['} for char in s: if char in mapping: # 右括号 # 弹出栈顶元素,如果栈为空则用'#'占位 top_element = stack.pop() if stack else '#' if mapping[char] != top_element: return False else: # 左括号 stack.append(char) # 如果栈为空,说明所有括号都匹配 return not stack2026年进阶问题:
追问1:如何找到第一个不匹配的位置?
def find_first_invalid(s: str) -> int: """ 返回第一个不匹配括号的索引 如果有效返回 -1 """ stack = [] mapping = {')': '(', '}': '{', ']': '['} for i, char in enumerate(s): if char in mapping: if not stack or stack[-1] != mapping[char]: return i # 右括号没有匹配的左括号 stack.pop() else: stack.append(i) # 存储索引而非字符 # 如果栈不为空,返回第一个未闭合的左括号 return stack[0] if stack else -1追问2:如果需要生成所有有效的括号组合呢?
这就变成了"生成括号"问题(LeetCode 22),需要用回溯法:
def generate_parentheses(n: int) -> List[str]: """ 生成n对括号的所有有效组合 """ result = [] def backtrack(current: str, open_count: int, close_count: int): if len(current) == 2 * n: result.append(current) return if open_count < n: backtrack(current + '(', open_count + 1, close_count) if close_count < open_count: backtrack(current + ')', open_count, close_count + 1) backtrack('', 0, 0) return result关键考点:
问题3:二叉树的最大深度(Maximum Depth of Binary Tree)
题目描述:
给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。示例:
3 / \ 9 20 / \ 15 7 最大深度 = 3解法1:递归(DFS)
class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def max_depth_recursive(root: TreeNode) -> int: """ 递归解法 - 深度优先搜索 时间复杂度:O(n),访问每个节点一次 空间复杂度:O(h),h是树的高度 """ if not root: return 0 left_depth = max_depth_recursive(root.left) right_depth = max_depth_recursive(root.right) return max(left_depth, right_depth) + 1解法2:迭代(BFS)
from collections import deque def max_depth_iterative(root: TreeNode) -> int: """ 迭代解法 - 广度优先搜索(层序遍历) 时间复杂度:O(n) 空间复杂度:O(w),w是最大宽度 """ if not root: return 0 queue = deque([root]) depth = 0 while queue: level_size = len(queue) depth += 1 for _ in range(level_size): node = queue.popleft() if node.left: queue.append(node.left) if node.right: queue.append(node.right) return depth2026年进阶问题:
追问1:如何判断一棵树是否平衡?
平衡二叉树定义:任意节点的左右子树高度差不超过1。
def is_balanced(root: TreeNode) -> bool: """ 判断二叉树是否平衡 时间复杂度:O(n) 空间复杂度:O(h) """ def check_height(node: TreeNode) -> int: """返回高度,如果不平衡返回-1""" if not node: return 0 left_height = check_height(node.left) if left_height == -1: return -1 right_height = check_height(node.right) if right_height == -1: return -1 if abs(left_height - right_height) > 1: return -1 return max(left_height, right_height) + 1 return check_height(root) != -1追问2:如何找到二叉树的直径?
直径定义:任意两个节点路径长度的最大值。
def diameter_of_binary_tree(root: TreeNode) -> int: """ 二叉树的直径 """ diameter = 0 def height(node: TreeNode) -> int: nonlocal diameter if not node: return 0 left_height = height(node.left) right_height = height(node.right) # 更新直径:经过当前节点的最长路径 diameter = max(diameter, left_height + right_height) # 返回当前节点的高度 return max(left_height, right_height) + 1 height(root) return diameter关键考点:
问题4:合并两个有序链表(Merge Two Sorted Lists)
题目描述:
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例:
输入: l1 = [1,2,4], l2 = [1,3,4] 输出: [1,1,2,3,4,4]解法:迭代
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def merge_two_lists(l1: ListNode, l2: ListNode) -> ListNode: """ 迭代合并两个有序链表 时间复杂度:O(m+n) 空间复杂度:O(1) """ dummy = ListNode() # 哨兵节点 current = dummy while l1 and l2: if l1.val <= l2.val: current.next = l1 l1 = l1.next else: current.next = l2 l2 = l2.next current = current.next # 连接剩余部分 current.next = l1 if l1 else l2 return dummy.next解法:递归
def merge_two_lists_recursive(l1: ListNode, l2: ListNode) -> ListNode: """ 递归解法 """ if not l1: return l2 if not l2: return l1 if l1.val <= l2.val: l1.next = merge_two_lists_recursive(l1.next, l2) return l1 else: l2.next = merge_two_lists_recursive(l1, l2.next) return l22026年进阶问题:
追问1:合并K个有序链表?
这是LeetCode 23,可以用优先队列(堆)解决:
import heapq def merge_k_lists(lists: List[ListNode]) -> ListNode: """ 合并K个有序链表 时间复杂度:O(N*logK),N是总节点数,K是链表数量 空间复杂度:O(K) """ dummy = ListNode() current = dummy # 创建最小堆 heap = [] # 将每个链表的头节点加入堆 for i, lst in enumerate(lists): if lst: heapq.heappush(heap, (lst.val, i, lst)) while heap: val, i, node = heapq.heappop(heap) current.next = node current = current.next if node.next: heapq.heappush(heap, (node.next.val, i, node.next)) return dummy.next追问2:如果链表非常大,内存有限怎么办?
• 使用归并排序的外部排序思想
• 分批读取、合并、写入磁盘
• 类似于大数据场景下的排序
关键考点:
问题5:爬楼梯问题(Climbing Stairs)
题目描述:
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶?示例:
输入: n = 2 输出: 2 解释: 有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶 输入: n = 3 输出: 3 解释: 有三种方法可以爬到楼顶。 1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶解法1:动态规划(DP)
def climb_stairs_dp(n: int) -> int: """ 动态规划解法 时间复杂度:O(n) 空间复杂度:O(n) """ if n <= 2: return n dp = [0] * (n + 1) dp[1] = 1 dp[2] = 2 for i in range(3, n + 1): dp[i] = dp[i-1] + dp[i-2] return dp[n]解法2:空间优化
def climb_stairs_optimized(n: int) -> int: """ 空间优化的动态规划 时间复杂度:O(n) 空间复杂度:O(1) """ if n <= 2: return n prev1, prev2 = 2, 1 for _ in range(3, n + 1): current = prev1 + prev2 prev2 = prev1 prev1 = current return prev1解法3:矩阵快速幂(进阶)
对于非常大的n(比如 n > 10^9),可以使用矩阵快速幂在 O(log n) 时间内求解:
def climb_stairs_matrix(n: int) -> int: """ 矩阵快速幂解法 时间复杂度:O(log n) 适用于n非常大的情况 """ import numpy as np def matrix_pow(mat, power): result = np.eye(len(mat), dtype=int) while power > 0: if power % 2 == 1: result = np.dot(result, mat) % 1000000007 mat = np.dot(mat, mat) % 1000000007 power //= 2 return result if n <= 2: return n base_matrix = np.array([[1, 1], [1, 0]], dtype=int) result_matrix = matrix_pow(base_matrix, n - 1) return int(result_matrix[0][0])2026年进阶问题:
变体1:每次可以爬1、2或3阶?
def climb_stairs_123(n: int) -> int: """ 每次可爬1、2或3阶 """ if n <= 2: return n if n == 3: return 4 # 111, 12, 21, 3 dp = [0] * (n + 1) dp[1], dp[2], dp[3] = 1, 2, 4 for i in range(4, n + 1): dp[i] = dp[i-1] + dp[i-2] + dp[i-3] return dp[n]变体2:不能连续爬两次2阶?
这是一个带约束的DP问题,需要增加状态维度。
关键考点:
上篇总结:这5道题为什么重要?
它们考察的核心能力:
2026年面试趋势:
1.不只是写代码:要能讲清楚思路。
2.要有 follow-up:准备好被追问。
3.要考虑优化:时间、空间、实际场景。
4.要展示工程思维:代码质量、可维护性。
下篇预告:
今天我们讲了前5道题,主要集中在:
✓数组与哈希表(Two Sum);
✓栈(Valid Parentheses);
✓树(Max Depth);
✓链表(Merge Lists);
✓动态规划(Climbing Stairs)。
在下篇中,我们将涵盖:
•问题6:LRU Cache;
•问题7:岛屿数量(Number of Islands);
•问题8:最小覆盖子串(Minimum Window Substring);
•问题9:设计一个分布式缓存系统;
•问题10:"请介绍一下你自己"。
还有:
• 30天备考计划;
• 每道题的练习建议;
• 常见错误和避坑指南……
敬请期待下篇:《2026年10月必练十大软件工程师面试问题(下):系统设计与行为面试》……