1. 算法刷题实战:LeetCode经典题目精解
今天我们来拆解LeetCode上的四道经典算法题,这些题目在面试中出现的频率相当高。作为一名经历过上百场技术面试的老兵,我深知掌握这些题目的解题思路对求职者有多重要。让我们直接进入正题,看看如何高效解决这些问题。
2. 122. 买卖股票的最佳时机 II
2.1 问题描述与分析
这道题要求我们在知道股票每天价格的情况下,通过多次买卖获取最大利润。与只能买卖一次的第一版不同,这里允许进行多次交易,但必须在再次购买前出售掉之前的股票。
关键点在于:我们可以在同一天既卖出又买入(相当于当天不操作),但不能同时持有多笔交易。
2.2 贪心算法解法
最直观的解法是贪心算法:
python复制def maxProfit(prices):
profit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i-1]:
profit += prices[i] - prices[i-1]
return profit
这个解法的核心思想是:只要今天的价格比昨天高,就进行买卖操作。虽然看起来像是每天都在交易,但实际上相当于抓住了所有的上升区间。
注意:这种解法只适用于可以无限次交易的情况。如果限制了交易次数,就需要用动态规划来解决了。
2.3 复杂度分析
- 时间复杂度:O(n),只需遍历一次数组
- 空间复杂度:O(1),只使用了常数级别的额外空间
3. 55. 跳跃游戏
3.1 问题理解
给定一个非负整数数组,每个元素代表在该位置可以跳跃的最大长度。我们需要判断是否能够从第一个位置跳到最后一个位置。
3.2 贪心策略实现
我们可以维护一个变量表示当前能够到达的最远位置:
python复制def canJump(nums):
max_reach = 0
for i in range(len(nums)):
if i > max_reach:
return False
max_reach = max(max_reach, i + nums[i])
return True
3.3 关键点解析
- 遍历数组时,始终更新能够到达的最远位置
- 如果在某个位置i时,i已经超过了之前能够到达的最远位置,说明无法到达终点
- 最后检查max_reach是否≥最后一个位置的下标
3.4 边界情况处理
- 数组长度为1时直接返回True
- 数组中包含0时需要特别注意,可能形成"陷阱"
4. 45. 跳跃游戏 II
4.1 问题升级
这是跳跃游戏的进阶版,要求找到到达数组末尾的最少跳跃次数。
4.2 贪心算法优化
我们可以使用类似BFS的思路:
python复制def jump(nums):
jumps = 0
current_end = 0
farthest = 0
for i in range(len(nums)-1):
farthest = max(farthest, i + nums[i])
if i == current_end:
jumps += 1
current_end = farthest
return jumps
4.3 算法解析
- 维护三个变量:jumps记录跳跃次数,current_end记录当前步数能到达的最远位置,farthest记录全局最远可达位置
- 遍历数组时不断更新farthest
- 当到达current_end时,必须进行一次跳跃,并更新current_end为farthest
4.4 复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(1)
5. 1005. K次取反后最大化的数组和
5.1 问题描述
给定一个整数数组和一个整数k,我们可以多次选择任意一个元素并将其取反(正变负,负变正)。在恰好进行k次取反后,返回数组可能的最大和。
5.2 解题思路
- 首先将数组按绝对值从大到小排序
- 遍历数组,优先对绝对值大的负数进行取反
- 如果k还有剩余,且为奇数,则对最小的正数进行取反
5.3 代码实现
python复制def largestSumAfterKNegations(nums, k):
nums.sort(key=lambda x: -abs(x))
for i in range(len(nums)):
if nums[i] < 0 and k > 0:
nums[i] = -nums[i]
k -= 1
if k % 2 == 1:
nums[-1] = -nums[-1]
return sum(nums)
5.4 注意事项
- 排序时要按绝对值排序
- 最后处理剩余的k值时,只需要考虑奇数次的情况
- 如果数组中有0,可以提前终止操作
6. 解题技巧总结
6.1 贪心算法适用场景
这四道题都使用了贪心算法的思想。贪心算法适用于问题具有最优子结构性质的情况,即局部最优解能导致全局最优解。
6.2 常见错误与调试技巧
- 边界条件处理不足:特别是数组长度为0或1的情况
- 变量更新时机错误:如在跳跃游戏中max_reach的更新位置
- 排序策略选择错误:如K次取反问题中需要按绝对值排序
6.3 面试实战建议
- 先明确问题要求,确保理解题意
- 从暴力解法开始,逐步优化
- 画图辅助理解,特别是跳跃游戏这类问题
- 考虑边界情况和特殊输入
在实际面试中,我通常会先写出暴力解法,然后分析其不足,再逐步优化。这样即使最终没能写出最优解,也能展示出解题思路和过程,给面试官留下好印象。
7. 扩展练习建议
为了真正掌握这些算法,我建议:
- 尝试用不同方法解决同一问题(如动态规划解法)
- 在LeetCode上寻找相似题目练习
- 记录自己的解题时间和错误,定期复盘
- 参与在线编程竞赛,锻炼快速解题能力
记住,算法能力的提升需要持续练习和总结。我个人的经验是,坚持每天解决2-3道中等难度题目,三个月后会有显著进步。