1. 算法刷题的价值与意义
作为一名程序员,算法刷题是提升编程能力的必经之路。我最近重新刷了LeetCode上的基础题125、122、130,并完成了进阶题65,这个过程让我对算法训练有了更深刻的认识。
算法刷题不仅仅是面试的敲门砖,更是培养编程思维的有效方式。通过反复练习同一道题目,我们能够发现之前忽略的细节,优化解法,甚至找到全新的思路。这种刻意练习对提升编程能力有着不可替代的作用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础题125解析:验证回文串
2.1 题目要求与初步思路
LeetCode第125题要求我们判断一个字符串是否是回文串。回文串是指正读反读都相同的字符串,忽略大小写和非字母数字字符。我的第一反应是使用双指针法,一个从前往后,一个从后往前,逐个比较字符。
python复制def isPalindrome(s: str) -> bool:
left, right = 0, len(s) - 1
while left < right:
while left < right and not s[left].isalnum():
left += 1
while left < right and not s[right].isalnum():
right -= 1
if s[left].lower() != s[right].lower():
return False
left += 1
right -= 1
return True
2.2 优化与注意事项
在实际编写代码时,有几个关键点需要注意:
- 边界条件的处理:空字符串、全是非字母数字字符的情况
- 大小写统一:比较前需要转换为统一大小写
- 指针移动:确保指针不会越界
提示:这道题看似简单,但很容易忽略非字母数字字符的处理,建议在纸上画出指针移动的过程,确保逻辑正确。
3. 基础题122解析:买卖股票的最佳时机II
3.1 问题分析与贪心算法
第122题是经典的股票买卖问题,允许无限次交易,求最大利润。这道题的关键在于理解"只要今天的价格比昨天高,就进行交易"这一贪心策略。
python复制def maxProfit(prices: List[int]) -> int:
profit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i-1]:
profit += prices[i] - prices[i-1]
return profit
3.2 动态规划解法对比
虽然贪心算法简洁高效,但为了深入理解这类问题,我还实现了动态规划解法:
python复制def maxProfit(prices: List[int]) -> int:
n = len(prices)
dp = [[0]*2 for _ in range(n)]
dp[0][0], dp[0][1] = 0, -prices[0]
for i in range(1, n):
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
return dp[n-1][0]
注意:动态规划解法虽然复杂度相同,但空间复杂度可以优化到O(1),建议尝试实现优化版本。
4. 基础题130解析:被围绕的区域
4.1 问题理解与DFS解法
第130题要求我们将被'X'完全包围的'O'替换为'X'。这道题的关键在于识别哪些'O'是不被包围的——即与边界相连的'O'。
我采用了DFS的解法:
- 首先处理边界上的'O',进行标记
- 然后遍历整个矩阵,将未标记的'O'改为'X'
- 最后恢复标记的'O'
python复制def solve(board: List[List[str]]) -> None:
if not board: return
m, n = len(board), len(board[0])
def dfs(i, j):
if 0 <= i < m and 0 <= j < n and board[i][j] == 'O':
board[i][j] = 'T'
for x, y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:
dfs(x, y)
for i in range(m):
dfs(i, 0)
dfs(i, n-1)
for j in range(n):
dfs(0, j)
dfs(m-1, j)
for i in range(m):
for j in range(n):
if board[i][j] == 'O':
board[i][j] = 'X'
elif board[i][j] == 'T':
board[i][j] = 'O'
4.2 BFS解法与性能对比
DFS在极端情况下可能导致栈溢出,因此我还实现了BFS版本:
python复制from collections import deque
def solve(board: List[List[str]]) -> None:
if not board: return
m, n = len(board), len(board[0])
queue = deque()
for i in range(m):
if board[i][0] == 'O':
queue.append((i, 0))
if board[i][n-1] == 'O':
queue.append((i, n-1))
for j in range(n):
if board[0][j] == 'O':
queue.append((0, j))
if board[m-1][j] == 'O':
queue.append((m-1, j))
while queue:
i, j = queue.popleft()
if 0 <= i < m and 0 <= j < n and board[i][j] == 'O':
board[i][j] = 'T'
for x, y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:
queue.append((x, y))
for i in range(m):
for j in range(n):
if board[i][j] == 'O':
board[i][j] = 'X'
elif board[i][j] == 'T':
board[i][j] = 'O'
5. 进阶题65解析:有效数字
5.1 问题分析与状态机解法
第65题要求验证字符串是否是有效数字,这是道典型的字符串处理难题。我采用了有限状态机(FSM)的解法,定义不同状态和转移条件。
python复制def isNumber(s: str) -> bool:
# 定义状态转移表
states = [
{'blank': 0, 'sign': 1, 'digit': 2, '.': 3}, # 0. 起始空格
{'digit': 2, '.': 3}, # 1. 符号
{'digit': 2, '.': 4, 'e': 5, 'blank': 8}, # 2. 数字
{'digit': 4}, # 3. 小数点(前无数字)
{'digit': 4, 'e': 5, 'blank': 8}, # 4. 小数点(后有数字)
{'sign': 6, 'digit': 7}, # 5. 指数e
{'digit': 7}, # 6. 指数符号
{'digit': 7, 'blank': 8}, # 7. 指数数字
{'blank': 8} # 8. 结束空格
]
current = 0
for c in s:
if c.isdigit():
action = 'digit'
elif c in '+-':
action = 'sign'
elif c == '.':
action = '.'
elif c.lower() == 'e':
action = 'e'
elif c == ' ':
action = 'blank'
else:
return False
if action not in states[current]:
return False
current = states[current][action]
return current in {2, 4, 7, 8}
5.2 正则表达式解法
虽然状态机解法清晰,但正则表达式更为简洁:
python复制import re
def isNumber(s: str) -> bool:
pattern = r'^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$'
return bool(re.fullmatch(pattern, s.strip()))
提示:正则表达式虽然简洁,但在面试中可能被要求解释其含义,建议同时掌握两种解法。
6. 刷题经验与技巧分享
6.1 如何高效刷题
- 分类练习:按题目类型(数组、字符串、树等)集中练习
- 一题多解:尝试用不同方法解决同一问题
- 总结模板:归纳常见题型的解题模式
- 定期复习:间隔重复已做过的题目
6.2 常见错误与避免方法
- 边界条件处理不足:总是测试空输入、极端值
- 变量命名随意:使用有意义的变量名
- 忽略时间/空间复杂度:明确分析算法效率
- 不写注释:关键步骤添加简明注释
6.3 个人刷题心得
在二刷这些题目时,我发现了之前忽略的细节:
- 对于125题,第一次忽略了连续非字母数字字符的情况
- 对于122题,最初没有理解贪心算法的正确性证明
- 对于130题,DFS实现时忘记了恢复标记的'O'
- 对于65题,状态机的设计不够严谨
这些经验让我明白,刷题不仅要追求数量,更要注重质量。每道题都应该彻底理解,并尝试多种解法。
