思维在 LeetCode 上卡住?这里是你的逃脱方案

发布: (2025年12月13日 GMT+8 14:21)
7 min read
原文: Dev.to

Source: Dev.to

介绍

你理解问题,但完全不知道从何开始。这种瘫痪是可以解决的。本指南提供一个具体的、一步一步的框架,帮助在毫无思路时生成解法——把“我什么都没有”转变为“我至少有一个起点”。

核心问题

空白思维的瘫痪源于试图直接跳到最优解,而不是先从任何可行的点开始。当面对一个不可能完成的任务(“完美求解”)时,大脑会冻结;但当任务是可实现的(“描述我们已知的内容”)时,大脑就会工作。

为什么重要

面试更惩罚沉默而不是错误的思路。即使思路不完整,口头表达你的思考过程也能展示解决问题的能力;而一阵空白则表明你无法应对未知。

框架(七步系统方法)

  1. 重新陈述问题
  2. 使用具体例子
  3. 先使用暴力法
  4. 识别瓶颈
  5. 模式匹配
  6. 约束分析
  7. 伪代码骨架

常见初学者错误

认为在写任何代码之前必须先得到完整的解法。部分进展永远胜过完美的沉默。

你将学到

  • 触发思考的问题模板(例如,“如果 n = 1 会怎样?”)
  • 将暴力法作为思考支架
  • 一步一步的提示系统,模拟专家在拆解陌生问题时的内部对话

卡住时的内部对话

“这需要 O(n log n)… 我该怎么做到?”
“我应该使用双指针… 或哈希表… 或者是动态规划?”
“什么是优雅的解法?”

你正在尝试在铺第一块砖之前就设计一座大教堂。当大脑看不到完美路径时,就会冻结。

步骤流程

1. 停止尝试直接求解 – 先理解问题

写下来(或大声说出):

  • “我需要找到/计算 …”
  • “已知 …”
  • “返回 …”

示例: Longest Substring Without Repeating Characters

重新陈述:
“给定一个字符串。我需要找到最长的连续子串,且其中没有字符出现两次。返回其长度。”

2. 手动演练一个小例子

输入: abcabcbb

手动追踪最长子串:

  • a → 长度 1
  • ab → 长度 2
  • abc → 长度 3(无重复)
  • abca → 停止,‘a’ 重复

对每个起始位置重复上述过程,可得最大长度为 3。

洞察: 你记录了已出现的字符,并在出现重复时重新开始。这个手动过程就是你的算法。

3. 编写暴力解法

def lengthOfLongestSubstring(s: str) -> int:
    max_len = 0
    n = len(s)

    # Try every possible substring
    for i in range(n):
        for j in range(i, n):
            substring = s[i:j+1]

            # Check if all characters are unique
            if len(substring) == len(set(substring)):
                max_len = max(max_len, len(substring))

    return max_len
  • 正确性: 是。
  • 复杂度: O(n³)(n² 个子串 × O(n) 的唯一性检查)。

即使它不是最优的,它也打破了空白状态,并提供了可运行的代码。

4. 识别瓶颈

昂贵的部分是对每个子串检查唯一性(set(substring))。

5. 模式匹配

暴力结构揭示了一个经典模式:

  • 遍历子数组
  • 维护状态(唯一性)
  • 更新结果

这对应 滑动窗口 / 双指针 模式。

6. 分析约束

典型约束: 1 ≤ s.length ≤ 5 × 10⁴

  • O(n³) 肯定会超时。
  • O(n²) 可能勉强可行。
  • O(n) 或 O(n log n) 为理想。

7. 起草伪代码(滑动窗口)

left = 0
max_len = 0
freq = empty hash map

for right in range(0, n):
    add s[right] to freq

    while any character count > 1:
        decrement freq[s[left]]
        left += 1

    max_len = max(max_len, right - left + 1)

return max_len

从这里开始,实现就很直接了。

完全卡住时的引导问题

  • 如果 n = 1 会怎样? → 基础情况。
  • 如果所有元素都相同会怎样? → 边界情况("aaaa" → 答案 1)。
  • 如果输入已排序会怎样? → 排序有帮助吗?
  • 我在纸上怎么解这道题? → 关注过程,而不是代码。
  • 我需要追踪哪些信息? → 确定状态/变量。
  • 我什么时候做决定? → 确定条件分支。
  • 我能把它拆成更小的子问题吗? → 例如,“对每个起点,找最长子串”。
  • 我能先解决一个更简单的版本吗? → 例如,“是否存在任意唯一子串?”
  • 如果我不考虑时间/空间约束会怎样? → 先找到正确解法,再优化。
  • 如果输入保证很小(n ≤ 10)会怎样? → 暴力解法可接受。

有效的面试开场

  1. 暴力法已知低效
    “我可以用嵌套循环在 O(n²) 内解决,但我觉得还有更好的办法。让我先把这段代码写出来。”

  2. 伪代码大纲
    “我还不知道具体实现细节,但我的思路是这样:” (写伪代码)

  3. 示例演练
    “让我先手动走一遍示例,看看会出现什么模式。”

这些方法展示了进展、结构以及愿意迭代的态度——正是面试官所看重的。

Back to Blog

相关文章

阅读更多 »