☰
五大经典算法题解析:从点击消除到大数乘法
2026/10/26 8:16:00 网站建设 项目流程

1. 笔试强训周练项目解析

这组题目来自某知名互联网企业的笔试强训周练第一周,包含了五个典型算法题:点击消除、数组中两个字符串的最小距离、dd爱框框、腐烂的苹果和大数乘法。这些题目覆盖了字符串处理、数组操作、广度优先搜索(BFS)和高精度计算等核心算法知识点,是检验程序员基础能力的经典题型。

我在实际刷题过程中发现,这些题目虽然表面看起来简单,但都设置了巧妙的边界条件和性能陷阱。下面我将逐题拆解最优解法和易错点,分享经过OJ系统验证的AC代码和调试心得。

2. 点击消除问题详解

2.1 问题描述与示例

给定一个仅由小写字母组成的字符串,当出现连续相同字符时点击消除它们。重复此过程直到无法继续消除,返回最终字符串。例如:

  • 输入 "abbaac" → 消除"bb"得"aaac" → 消除"aaa"得"c"
  • 输入 "abccba" → 消除"cc"得"abba" → 消除"bb"得"aa" → 消除"aa"得""

2.2 栈解法实现

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

关键点:使用栈结构可以在O(n)时间复杂度和O(n)空间复杂度下高效解决问题。每当遇到与栈顶相同的字符时就弹出,否则压入新字符。

2.3 常见错误分析

  1. 双指针误用:尝试用双指针原地修改会遇到字符消除后新产生的连续对无法处理的问题
  2. 递归解法:虽然直观但空间复杂度会达到O(n²),在长字符串时导致栈溢出
  3. 边界条件:空字符串输入、全消除情况、交替字符等情况需要特殊处理

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

3.1 问题定义

给定一个字符串数组strs和两个特定字符串str1、str2,找出它们在数组中最近的出现距离。例如:

  • 输入:strs = ["a","b","c","d","a"], str1 = "a", str2 = "d"
  • 输出:2("a"在索引0,"d"在索引3)

3.2 最优解法代码

def min_distance(strs, str1, str2): idx1 = idx2 = -1 min_dist = float('inf') for i, s in enumerate(strs): if s == str1: idx1 = i if idx2 != -1: min_dist = min(min_dist, abs(idx1 - idx2)) elif s == str2: idx2 = i if idx1 != -1: min_dist = min(min_dist, abs(idx1 - idx2)) return min_dist if min_dist != float('inf') else -1

3.3 性能优化要点

  1. 单次遍历:记录最近出现的str1和str2位置,实时更新最小距离
  2. 短路判断:当找到str1和str2相邻出现时可立即返回1
  3. 预处理优化:对于多次查询场景,可预先建立{str: [indexes]}的字典

4. dd爱框框问题解析

4.1 滑动窗口经典应用

给定正整数数组和target,寻找长度最小的连续子数组,其和≥target。这是典型的滑动窗口问题:

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

4.2 边界条件测试用例

输入数组target预期输出测试目的
[2,3,1,2,4,3]72常规情况
[1,4,4]41单个元素满足
[1,1,1]50无解情况
[10,2,3]61首元素独立满足

5. 腐烂的苹果问题

5.1 多源BFS实现

题目描述:网格中0表示空,1表示新鲜苹果,2表示腐烂苹果。每分钟腐烂相邻新鲜苹果,求全部腐烂所需时间。

from collections import deque def orangesRotting(grid): m, n = len(grid), len(grid[0]) q = deque() fresh = 0 # 初始化队列和新鲜苹果计数 for i in range(m): for j in range(n): if grid[i][j] == 2: q.append((i,j)) elif grid[i][j] == 1: fresh += 1 if fresh == 0: return 0 dirs = [(0,1),(1,0),(0,-1),(-1,0)] minutes = -1 while q: minutes += 1 for _ in range(len(q)): x,y = q.popleft() for dx,dy in dirs: 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 q.append((nx,ny)) return minutes if fresh == 0 else -1

5.2 复杂度分析

  • 时间复杂度:O(mn),每个节点最多入队一次
  • 空间复杂度:O(mn),最坏情况下队列需要存储所有腐烂苹果

6. 大数乘法实现

6.1 竖式乘法模拟

实现字符串表示的大整数乘法,如"123"×"456"="56088":

def multiply(num1: str, num2: str) -> str: if num1 == "0" or num2 == "0": return "0" m, n = len(num1), len(num2) res = [0] * (m + n) for i in range(m-1, -1, -1): for j in range(n-1, -1, -1): mul = int(num1[i]) * int(num2[j]) p1, p2 = i+j, i+j+1 total = mul + res[p2] res[p2] = total % 10 res[p1] += total // 10 # 去除前导零 i = 0 while i < len(res) and res[i] == 0: i += 1 return ''.join(map(str, res[i:]))

6.2 关键步骤说明

  1. 结果位数:m位数×n位数结果最多m+n位
  2. 位置关系:num1[i]×num2[j]的结果应放在res[i+j]和res[i+j+1]
  3. 进位处理:从低位到高位逐步处理进位
  4. 前导零:最终结果需要去除前导零

7. 字符串处理技巧总结

7.1 高频字符串操作

根据热词分析,这些字符串操作最常被搜索:

  1. 字符串截取:s[start:end]
  2. 分割处理:split()与正则表达式结合
  3. 模式匹配:KMP算法优化搜索
  4. 类型转换:安全处理字符串与数字转换

7.2 实用代码片段

# 手机号脱敏处理 def mask_phone(phone: str) -> str: return phone[:3] + '****' + phone[-4:] if len(phone) == 11 else phone # 多分隔符分割 import re def complex_split(s: str): return re.split(r'[,;|\s]+', s) # 首个唯一字符 def first_unique(s: str) -> int: from collections import Counter count = Counter(s) for i, ch in enumerate(s): if count[ch] == 1: return i return -1

在实际笔试中,建议先写出基础解法再考虑优化,通常时间复杂度在O(n²)以内都能通过常规测试用例。对于大数问题要注意Python的无限精度特性可能使问题简化,但面试官往往期望看到算法实现本身。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询