30 秒识别Q1 · 977 Squares of a Sorted Array:给一个已排序(含负数)的数组,返回每个数平方后的有序数组。你的第一反应是哪个模式?
看答案
双指针。平方后最大值只可能出现在两端,所以从两端向中间收、从后往前填结果。看到「已排序」+「结果也要有序」就该想到相向指针,而不是排序后再排一次。
相向双指针为什么对:数组有序时,nums[l] + nums[r] 太小,那么 nums[l] 配右边任何数都太小,这一整行候选一次性作废,l 才敢往前走。任何相向双指针题,你都应该能说出这句「作废了谁」——说不出来就是在碰运气。
同向快慢指针是另一件事:一个负责看、一个负责写(原地覆盖),或者一个走两步、一个走一步(找中点、判环)。它不要求有序,要求的是两个指针的相对关系本身就是答案。
| 题面出现… | 想到 |
|---|---|
| 「已排序数组」+ 找一对 / 三个数满足条件 | 相向双指针(模板 A) |
| 「回文 / 对称 / 首尾比较」 | 相向双指针(模板 A) |
| 「容器 / 面积 / 两根柱子」 | 相向 + 短板先动(模板 A 的度量换成面积) |
| 「原地去重 / 移除元素 / 把某类挪到前面」 | 同向快慢(模板 B) |
| 「3Sum / 4Sum / 最接近的三数之和」 | 排序 + 固定 k−2 个 + 相向 |
| 链表「找中点 / 判环 / 倒数第 n 个」 | 快慢指针,模板在第 06 章 |
「两数之和」在无序数组上是哈希(第 01 章),排序后才轮到双指针——如果题目没给有序、也不允许排序(要原下标),就别硬套。「连续子数组满足某条件」左右指针都从左端出发、且窗口内状态要维护,那是滑动窗口(第 03 章),不是相向双指针。
■ 【骨架】 不变,闭着眼默写 ■ 【插槽】 随题变化,写题前先问自己填什么
def two_sum_sorted(nums, target):
l, r = 0, len(nums) - 1 # 【骨架】两端起步
while l < r: # 【骨架】相遇即结束
cur = nums[l] + nums[r] # 【插槽】当前候选的度量:和 / 面积 / 是否相等
if cur == target: # 【插槽】命中条件
return [l, r] # 【插槽】答案形式
if cur < target: # 【插槽】谁动:小了就让左边变大
l += 1 # 【骨架】
else:
r -= 1 # 【骨架】
return []
def remove_val(nums, val):
slow = 0 # 【骨架】slow = 下一个要写入的位置
for fast in range(len(nums)): # 【骨架】fast 负责看,slow 负责写
if nums[fast] != val: # 【插槽】保留条件:去重 / 非零 / 满足谓词
nums[slow] = nums[fast] # 【骨架】
slow += 1 # 【骨架】
return slow # 【插槽】答案:新长度 / 就地改好的数组
nums[slow:] 之后的内容按题目要求可以是任何值。isalnum() 过滤 + lower(),别先拼出一个干净字符串再比较——面试官想看的是 O(1) 空间。nums[i] > 0 时提前 break 是常见加分点。if i and nums[i] == nums[i-1]: continue;命中后左指针跳过重复;右指针同理。只写一处就会出现重复三元组——这是 3Sum 最常见的 WA。while l < r 还是 l <= r——要一对不同元素用 <;在有序数组上二分式地找单个位置才可能用 <=。回文判断用 < 即可,中间那个字符不需要和自己比。[1,8,6,2,5,4,8,3,7] 会给出 8 而不是 49。30 秒识别Q1 · 977 Squares of a Sorted Array:给一个已排序(含负数)的数组,返回每个数平方后的有序数组。你的第一反应是哪个模式?
双指针。平方后最大值只可能出现在两端,所以从两端向中间收、从后往前填结果。看到「已排序」+「结果也要有序」就该想到相向指针,而不是排序后再排一次。
30 秒识别Q2 · 26 Remove Duplicates from Sorted Array:在已排序数组上原地去重,返回去重后的长度。你的第一反应是哪个模式?
双指针(模板 B)。保留条件从 != val 换成 != nums[slow-1],骨架一行没变。用 set 也能去重,但破坏顺序、且不是原地。
30 秒识别Q3 · 给定正整数数组和 target,求和 ≥ target 的最短连续子数组长度。你的第一反应是哪个模式?
滑动窗口,不是本章——两个指针都从左端出发、右扩左缩,窗口内要维护「当前和」这个状态。相向双指针从两端起步、不维护状态,是完全不同的两件事。见第 03 章。
每章自测都会混入恰好一道非本章题,防止「读哪章选哪章」的条件反射;题面也一律取自本章未收录的题,避免凭记忆而非凭信号作答。