1. 算法训练营初体验:二分查找与数组操作实战
今天是我参加代码随想录算法训练营的第一天,主要攻克了三道经典题目:LeetCode704二分查找、LeetCode27移除元素和LeetCode977有序数组的平方。作为算法入门者,这三道题让我深刻体会到基础算法思想的重要性,也积累了不少实战经验。下面分享我的解题思路和踩坑记录。
1.1 为什么选择这三道题作为起点?
这三道题看似简单,实则涵盖了算法学习的核心基础:
- 二分查找(704题):理解循环不变量和边界处理
- 双指针法(27题):原地修改数组的高效技巧
- 平方排序(977题):双指针的进阶应用场景
提示:新手常犯的错误是直接看题解,建议先自己思考30分钟再参考解法,这样的学习效果最好。
2. LeetCode704:二分查找深度解析
2.1 标准二分查找实现
最经典的二分查找问题,给定升序数组和目标值,返回目标值索引或-1。关键点在于区间定义和边界处理:
python复制def search(nums, target):
left, right = 0, len(nums) - 1 # 闭区间
while left <= right: # 注意等号
mid = left + (right - left) // 2 # 防溢出
if nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
else:
return mid
return -1
2.2 易错点与调试技巧
- 区间定义混乱:闭区间[left, right]对应left <= right,开区间则不同
- mid计算溢出:使用left + (right-left)//2而非(left+right)//2
- 边界更新错误:left=mid+1而非left=mid,避免死循环
实测案例:在数组[1,3,5,7]中查找3
- 第一轮:mid=1(值3),直接命中
- 若误写while left < right,会漏查边界情况
3. LeetCode27:移除元素的双指针艺术
3.1 快慢指针解法
题目要求原地移除所有等于val的元素,返回新长度。暴力解法O(n²)不够高效,双指针可将复杂度降至O(n):
python复制def removeElement(nums, val):
slow = 0
for fast in range(len(nums)):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
return slow
3.2 指针移动的底层逻辑
- 快指针fast:遍历数组的侦察兵
- 慢指针slow:构建新数组的工程师
- 赋值操作:nums[slow] = nums[fast]实现原地修改
注意:这题与26题去重非常相似,都是双指针的经典应用场景。建议对比练习。
4. LeetCode977:有序数组平方的优雅处理
4.1 暴力解法与优化空间
最直观的思路是先平方后排序:
python复制def sortedSquares(nums):
return sorted(x*x for x in nums) # O(nlogn)
但未利用原数组已排序的特性,通过双指针可以优化到O(n):
4.2 双指针从两端向中间逼近
python复制def sortedSquares(nums):
n = len(nums)
res = [0] * n
left, right = 0, n - 1
pos = n - 1 # 从后往前填充
while left <= right:
if abs(nums[left]) > abs(nums[right]):
res[pos] = nums[left] ** 2
left += 1
else:
res[pos] = nums[right] ** 2
right -= 1
pos -= 1
return res
4.3 指针移动策略分析
- 比较绝对值:因为负数平方后可能变大
- 从后往前填:确保最大值放在最后
- 终止条件:left <= right保证中间元素被处理
实测案例:对于输入[-4,-1,0,3,10]
- 第一轮:比较|-4|和|10|,填10²=100
- 第二轮:比较|-4|和|3|,填(-4)²=16
- 最终结果:[0,1,9,16,100]
5. 训练营第一天的核心收获
5.1 算法思想提炼
-
二分查找三要素:
- 有序性前提
- 区间定义明确
- 边界更新正确
-
双指针使用场景:
- 原地修改数组(快慢指针)
- 有序数组合并(对向指针)
5.2 调试与优化经验
- 对于二分查找,建议先写出区间定义再写循环条件
- 双指针问题可以画图辅助理解指针移动
- 边界条件测试用例必不可少:
- 空数组
- 单元素数组
- 全相同元素数组
- 首尾元素特殊情况
5.3 后续练习建议
-
二分查找变种:
- 35.搜索插入位置
- 34.在排序数组中查找元素的第一个和最后一个位置
-
双指针进阶:
- 283.移动零
- 844.比较含退格的字符串
-
综合应用:
- 209.长度最小的子数组
- 59.螺旋矩阵II
第一天训练让我明白,算法学习不能急于求成。每道题都要吃透背后的思想,反复练习直到能独立写出bug-free的代码。建议准备错题本记录典型错误,这对后续复习非常有帮助。