news 2026/8/24 6:20:21

算法笔试高频题型解析:栈、滑动窗口与BFS实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法笔试高频题型解析:栈、滑动窗口与BFS实战

1. 笔试强训Week1题目解析

作为一名经历过无数次笔试面试的老程序员,我深知算法题在技术面试中的重要性。今天我要分享的这套"笔试强训Week1"题目,包含了字符串处理、数组操作、模拟题和大数运算等经典题型,都是各大厂笔试中的高频考点。

这套题目由浅入深,覆盖了以下五个经典问题:

  1. 点击消除(字符串栈应用)
  2. 数组中两个字符串的最小距离(数组遍历技巧)
  3. dd爱框框(滑动窗口/前缀和)
  4. 腐烂的苹果(BFS应用)
  5. 大数乘法(字符串模拟运算)

接下来我将逐个拆解每道题的核心思路和解题技巧,分享我在实际编码和面试中积累的经验。

2. 点击消除:字符串与栈的完美结合

2.1 题目理解与示例分析

点击消除的规则是:当出现相邻相同字符时,它们会被消除。这个过程会持续进行,直到没有可以消除的字符为止。例如:

  • 输入 "abbaca" → 消除 "bb" → "aaca" → 消除 "aa" → "ca"

这道题本质上考察的是字符串处理和栈的应用。很多同学第一反应是用循环不断扫描字符串进行消除,但这种做法在最坏情况下(如"aaaaaa")时间复杂度会达到O(n²)。

2.2 最优解:栈的应用

更高效的解法是使用栈结构:

def remove_duplicates(s: str) -> str: stack = [] for char in s: if stack and stack[-1] == char: stack.pop() else: stack.append(char) return ''.join(stack)

时间复杂度:O(n) 空间复杂度:O(n)

关键点:当遇到相同字符时弹出栈顶元素,否则压入栈。最后栈中剩余字符就是结果。

2.3 边界条件与测试用例

需要特别注意的边界情况:

  1. 空字符串输入
  2. 全部字符都可消除的情况(如"aaaa")
  3. 无任何消除的情况(如"abcde")
  4. 交替消除的情况(如"abba"→"")

3. 数组中两个字符串的最小距离

3.1 问题描述

给定一个字符串数组strs和两个字符串str1、str2,找出它们在数组中最近的距离。例如: strs = ["1","3","3","3","2","3","1"], str1 = "1", str2 = "2" → 输出2

3.2 双指针解法

最直观的解法是记录两个字符串所有出现位置,然后计算最小差值,但这样需要O(n²)时间复杂度。

更优解法是在一次遍历中记录最近出现的str1和str2位置:

def min_distance(strs, str1, str2): index1 = -1 # str1最近出现位置 index2 = -1 # str2最近出现位置 min_dist = float('inf') for i, s in enumerate(strs): if s == str1: index1 = i if index2 != -1: min_dist = min(min_dist, index1 - index2) elif s == str2: index2 = i if index1 != -1: min_dist = min(min_dist, index2 - index1) return min_dist if min_dist != float('inf') else -1

3.3 优化与变种

  1. 如果数组中有大量重复查询,可以预处理建立哈希表记录每个字符串的所有位置
  2. 变种题:求多个字符串的最小距离(需要扩展记录多个索引)
  3. 如果str1和str2相同的情况需要特殊处理

4. dd爱框框:滑动窗口的经典应用

4.1 题目理解

给定一个数组和一个目标值x,找到和≥x的最短连续子数组。例如: nums = [1,2,3,4,5], x = 9 → 输出[4,5]

4.2 滑动窗口解法

这类求连续子数组的问题通常可以用滑动窗口解决:

def min_subarray(nums, x): left = 0 current_sum = 0 min_len = float('inf') result = [] for right in range(len(nums)): current_sum += nums[right] while current_sum >= x: if right - left + 1 < min_len: min_len = right - left + 1 result = nums[left:right+1] current_sum -= nums[left] left += 1 return result if min_len != float('inf') else []

4.3 复杂度分析与优化

时间复杂度:O(n) —— 每个元素最多被访问两次 空间复杂度:O(1)

实际编码时要注意窗口滑动条件和结果更新的时机,这是最容易出错的地方。

5. 腐烂的苹果:多源BFS应用

5.1 问题描述

给定一个m×n的网格,每个格子可能有:

  • 0表示空单元格
  • 1表示新鲜苹果
  • 2表示腐烂苹果

每分钟,腐烂苹果会使相邻(上下左右)的新鲜苹果腐烂。求所有苹果腐烂所需时间,或返回-1表示不可能。

5.2 多源BFS解法

典型的多源广度优先搜索问题:

def orangesRotting(grid): from collections import deque m, n = len(grid), len(grid[0]) queue = deque() fresh = 0 time = 0 # 初始化:记录所有腐烂苹果位置和新鲜苹果数量 for i in range(m): for j in range(n): if grid[i][j] == 2: queue.append((i, j)) elif grid[i][j] == 1: fresh += 1 # 如果没有新鲜苹果 if fresh == 0: return 0 # BFS过程 directions = [(-1,0),(1,0),(0,-1),(0,1)] while queue and fresh > 0: time += 1 for _ in range(len(queue)): x, y = queue.popleft() for dx, dy in directions: nx, ny = x + dx, y + dy if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == 1: grid[nx][ny] = 2 fresh -= 1 queue.append((nx, ny)) return time if fresh == 0 else -1

5.3 复杂度与注意事项

时间复杂度:O(mn) 空间复杂度:O(mn)

关键点:

  1. 需要先统计初始状态的新鲜苹果数量
  2. 使用队列层级遍历保证时间计算准确
  3. 最后要检查是否还有剩余新鲜苹果

6. 大数乘法:字符串模拟运算

6.1 问题背景

当数字超过语言基本类型的表示范围时(如1000位的整数),需要用字符串表示并模拟手工乘法过程。

6.2 算法思路

模拟竖式乘法:

  1. 从右到左逐位相乘
  2. 处理进位
  3. 累加中间结果
def multiply(num1: str, num2: str) -> str: if num1 == "0" or num2 == "0": return "0" m, n = len(num1), len(num2) result = [0] * (m + n) # 从低位到高位逐位相乘 for i in range(m-1, -1, -1): for j in range(n-1, -1, -1): mul = (ord(num1[i]) - ord('0')) * (ord(num2[j]) - ord('0')) p1, p2 = i + j, i + j + 1 total = mul + result[p2] result[p2] = total % 10 result[p1] += total // 10 # 去除前导零 start = 0 while start < len(result) and result[start] == 0: start += 1 return ''.join(map(str, result[start:]))

6.3 优化与边界处理

  1. 处理输入为"0"的情况直接返回
  2. 结果数组大小设为m+n足够存放乘积
  3. 注意去除前导零
  4. 可以优化Karatsuba算法达到O(n^1.585)复杂度

7. 综合训练建议

通过这五道题的训练,可以掌握以下核心技能:

  1. 栈在字符串处理中的应用
  2. 数组遍历与双指针技巧
  3. 滑动窗口解决连续子数组问题
  4. 多源BFS在网格问题中的应用
  5. 字符串模拟大数运算

在实际笔试中,建议:

  • 先理解清楚题目要求,多举几个例子
  • 分析时间空间复杂度,选择合适算法
  • 注意边界条件和特殊输入
  • 写代码时保持清晰的变量命名和注释
  • 完成后用测试用例验证

我在面试候选人时发现,能够清晰解释解题思路并处理边界条件的候选人,往往在实际工作中也表现出色。算法题不仅是考察编码能力,更是考察问题分析和解决能力的窗口。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 6:18:58

软件测试面试全攻略:核心考点与自动化测试实践

1. 软件测试面试的核心考察维度软件测试岗位的面试通常围绕技术能力、项目经验和思维逻辑三个维度展开。技术能力考察的是候选人对测试理论、工具和流程的掌握程度&#xff1b;项目经验则关注实际工作场景中的问题解决能力&#xff1b;思维逻辑则体现在测试用例设计、缺陷分析等…

作者头像 李华
网站建设 2026/8/24 6:18:51

ENVI实战:遥感生态指数RSEI四大核心指数计算全流程与避坑指南

1. 项目概述&#xff1a;从遥感数据到生态健康“体检单”搞遥感生态评价的朋友&#xff0c;对“遥感生态指数”这个名字肯定不陌生。它就像给一片区域做一次全面的“生态体检”&#xff0c;而这份体检报告的核心&#xff0c;就是由四个关键指标——绿度、湿度、干度和热度——综…

作者头像 李华
网站建设 2026/8/24 6:16:58

Art Design Pro 快速上手指南:5分钟跑通 Vue3 后台管理系统

Art Design Pro 快速上手指南&#xff1a;5分钟跑通 Vue3 后台管理系统 【免费下载链接】art-design-pro A Vue 3 admin dashboard template using Vite TypeScript Element Plus | vue3 admin | vue-admin — focused on user experience and visual design. 项目地址: ht…

作者头像 李华
网站建设 2026/8/24 6:14:48

RS-232/RS-485/RS-422串口通信:原理、选型与实战避坑指南

1. 项目概述&#xff1a;为什么我们还在讨论这些“老古董”&#xff1f; 干了这么多年嵌入式开发&#xff0c;调试过无数串口设备&#xff0c;我发现一个挺有意思的现象&#xff1a;无论技术怎么迭代&#xff0c;项目里总少不了RS-232、RS-485、RS-422这几个“老面孔”。新人看…

作者头像 李华
网站建设 2026/8/24 6:14:47

Crowbar 新手教程:VPK 解包、改资源与重新打包

Crowbar 新手教程&#xff1a;VPK 解包、改资源与重新打包 【免费下载链接】Crowbar Crowbar - GoldSource and Source Engine Modding Tool 项目地址: https://gitcode.com/gh_mirrors/crow/Crowbar 假设你手上有一个游戏的 .vpk 包&#xff0c;想把里面的贴图、模型拿…

作者头像 李华
网站建设 2026/8/24 6:14:31

基于OpenClaw AI Agent与微信小程序的物联网远程控制系统实践

1. 项目概述&#xff1a;当微信遇上AI Agent&#xff0c;远程“养龙虾”成为可能最近在AI和开发者圈子里&#xff0c;一个名为“OpenClaw”的项目悄然走红&#xff0c;而让它出圈的&#xff0c;是一个听起来有点“赛博朋克”的场景&#xff1a;在微信里运行OpenClaw&#xff0c…

作者头像 李华