LeetCode 547:省份数量,把邻接矩阵看成图的连通分量

题目要求 给你一个 n x n 的矩阵 isConnected,其中有 n 个城市。 如果 isConnected[i][j] == 1,说明城市 i 和城市 j 直接相连;如果两个城市可以通过若干个直接相连的城市互相到达,它们就属于同一个省份。 题目要求返回省份的总数。 这里最容易误解的一点是:题目不是让我们数矩阵里有多少个 1,也不是只看直接相连的城市对。它真正要数的是: 直接或间接连接在一起的城市组有多少个。 换成图的语言,就是: 给定一个无向图的邻接矩阵,返回这个图的连通分量数量。 输入输出 输入:isConnected: List[List[int]] 输出:省份数量 int 城市编号可以按 0..n-1 理解。 isConnected[i][j] == 1 表示城市 i 和城市 j 之间有边。 isConnected[i][j] == 0 表示城市 i 和城市 j 没有直接边。 示例 1 输入:isConnected = [ [1, 1, 0], [1, 1, 0], [0, 0, 1] ] 输出:2 城市 0 和城市 1 直接相连,所以它们属于同一个省份。 ...

2026年5月27日 · 6 分钟 · map[name:Jeanphilo]

为什么 AI 在代码领域最先自动化

代码领域之所以最早得到 AI 自动化,不只是因为代码适合大模型,而是因为软件工程已经拥有版本控制、测试、增量提交和回滚机制。其他领域并不是没有评价标准,而是缺少把标准绑定到中间版本上的工作流。文章、小说、视频、3D 模型等复杂作品也能被拆解、验证、冻结和追溯;而且文字领域天然拥有经典作品、评论和写作理论作为 reference corpus。一旦这些参照物被转成任务、rubric 和 checkpoint,AI 可能比在代码领域释放出更强的能力。

2026年5月21日 · 4 分钟 · map[name:Jeanphilo]

Docker 容器如何使用宿主机 Clash 代理

副标题 / 摘要 宿主机能访问 OpenAI,不代表 Docker 容器也能访问。本文记录一次 sub2api 容器无法完成 OpenAI OAuth 的排障过程,并给出一种不绑定 Docker 网段 IP 的配置方式。 目标读者 使用 Docker Compose 部署服务的开发者 在服务器上使用 Clash、Mihomo 或类似代理的用户 遇到容器内访问 OpenAI、GitHub、Google 等服务超时的人 需要理解 127.0.0.1、Docker 网桥和宿主机代理关系的人 背景 / 动机 问题表面上是 sub2api 后台提示: 未设置代理,当前服务器无法直连 OpenAI,导致 OpenAI OAuth 请求失败。 请先选择可访问 OpenAI 的代理后重试;如果授权码已失效,请重新生成授权链接。 容易产生的疑问是:我的电脑明明可以访问 OpenAI,Codex 也能用,为什么 Docker 里的服务不行? 原因是 Codex、浏览器、终端和 Docker 容器不一定走同一条网络路径。宿主机上的程序可以使用 127.0.0.1:7890 代理,但容器里的 127.0.0.1 指向的是容器自己,不是宿主机。 核心概念 宿主机的 127.0.0.1 不是容器的 127.0.0.1 如果 Clash 只监听: 127.0.0.1:7890 那么只有宿主机本机进程能访问它。Docker 容器访问 127.0.0.1:7890 时,访问的是容器内部的 7890 端口,通常什么都没有。 ...

2026年5月15日 · 3 分钟 · map[name:Jeanphilo]

LeetCode 198:打家劫舍,从偷或不偷推出一维 DP

题目要求 输入输出 输入:整数数组 nums nums[i] 表示第 i 间房子的金额 不能偷相邻房子 输出:返回最多能偷到的金额 约束:1 <= nums.length <= 100,0 <= nums[i] <= 400 示例 输入:nums = [1,2,3,1] 输出:4 解释:偷下标 0 和下标 2,金额 1 + 3 = 4 输入:nums = [2,7,9,3,1] 输出:12 解释:偷下标 0、2、4,金额 2 + 9 + 1 = 12 这篇只用 Python,从这个二选一冲突推出一维 DP。 从 [1,2,3,1] 的相邻冲突开始 看例子: nums = [1,2,3,1] 如果偷下标 2 的房子,金额是 3,那么下标 1 和下标 3 都不能偷。 如果不偷下标 2,答案可能来自前面下标 0..1 的最优结果。 所以走到某一间房时,核心选择只有两个: ...

2026年5月3日 · 3 分钟 · map[name:Jeanphilo]

LeetCode 70:爬楼梯,从 dp[i] 含义推出一维 DP

题目要求 输入输出 输入:整数 n 含义:爬到第 n 阶楼顶 每次可以爬 1 或 2 阶 输出:返回到达楼顶的不同走法数量 约束:1 <= n <= 45 示例 输入:n = 2 输出:2 解释:1+1,2 输入:n = 3 输出:3 解释:1+1+1,1+2,2+1 这篇只用 Python,从 dp[i] 的含义一步一步推出最终代码。 从 n = 3 的最后一步开始 先看最小能暴露转移的例子: n = 3 到第 3 阶的最后一步只可能来自: 第 2 阶,再走 1 阶 第 1 阶,再走 2 阶 所以“到第 3 阶的方法数”不是凭空算出来的,而是来自两个更小的位置。 Step 1:先定义更小的问题 直接问“到第 n 阶有几种走法”太大。先定义: dp[i] = 到达第 i 阶的方法数 注意这里的 i 是楼梯位置,不是数组下标含义上的第几个元素。 ...

2026年5月3日 · 4 分钟 · map[name:Jeanphilo]

LeetCode 746:使用最小花费爬楼梯,从 top 位置推出 dp

题目要求 输入输出 输入:整数数组 cost cost[i] 表示踩到第 i 阶的代价 每次可以爬 1 或 2 阶 可以从下标 0 或下标 1 开始 输出:返回到达楼顶的最小花费 约束:2 <= cost.length <= 1000,0 <= cost[i] <= 999 示例 输入:cost = [10,15,20] 输出:15 解释:从下标 1 开始,付 15 后直接到达 top 输入:cost = [1,100,1,1,1,100,1,1,100,1] 输出:6 从 [10,15,20] 的 top 位置开始 先看最小例子: cost = [10,15,20] 楼顶不是下标 2,而是在最后一阶之后的位置,可以记为位置 3。 到达 top 位置 3 的最后一步只可能来自: 位置 2,付 cost[2] 位置 1,付 cost[1] 这题最容易错的地方就在这里:我们要求的是“到达 top 的花费”,不是“到达最后一个下标的花费”。 ...

2026年5月3日 · 3 分钟 · map[name:Jeanphilo]

LeetCode 53:最大子数组和,从 dp[i] 含义推出 Kadane

题目要求 输入输出 输入:整数数组 nums 输出:返回连续非空子数组的最大和 子数组必须连续 至少选一个元素 约束:1 <= nums.length <= 10^5,-10^4 <= nums[i] <= 10^4 示例 输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:[4,-1,2,1] 的和最大,为 6 输入:nums = [1] 输出:1 这篇只用 Python,从 dp[i] 的含义一步一步推出 Kadane 算法。 从 [-2,1,-3,4] 的断点开始 看一个前缀例子: nums = [-2, 1, -3, 4] 如果走到 4,有两种选择: 把前面的某个连续子数组接到 4 前面 从 4 自己重新开始 这里的关键不是“所有子数组怎么枚举”,而是: 当我们决定一个最优子数组必须以当前位置结尾时,它的来源只有两种:接上前一个位置的最优结尾,或者从当前位置重新开始。 这就是一维 DP 的入口。 Step 1:先定义一个更小的问题 直接问“整个数组的最大子数组和是多少”太大。我们先强加一个限制: 如果子数组必须以第 i 个元素结尾,它的最大和是多少? 这个值记为 dp[i]。 这里的 dp[i] 不是“前 i 个元素里的最大子数组和”。它更窄: ...

2026年5月3日 · 3 分钟 · map[name:Jeanphilo]

LeetCode 78:子集,从搜索树推出 startIndex 回溯模板

题目要求 输入输出 输入:nums,长度 1 <= nums.length <= 10 元素范围:-10 <= nums[i] <= 10 所有元素互不相同 输出:返回 nums 的所有可能子集 顺序:结果顺序不限,子集内部不需要考虑排列顺序 示例 输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] 这篇只用 Python 构造一个最小可运行解法。 从 [1,2] 的搜索树开始 最小但有分叉的例子是: nums = [1,2] 答案应该是: [], [1], [1,2], [2] 注意这里没有 [2,1]。这说明问题不是“随便排列所有选择”,而是“每个元素选或不选,且同一组元素只出现一次”。 如果把构造过程画成树: [] |- [1] | |- [1,2] |- [2] 这棵树暴露出两个事实: 每个节点都是一个合法子集。 进入 [1] 之后,后面只能继续看 2,不能回头再选 1 或生成 [2,1]。 Step 1:先说清楚一个递归层在解决什么 如果当前已经选出一个 path,剩下的问题是: 从某个起点之后的元素里,继续选择若干个元素,扩展当前 path。 这个“某个起点”必须被记下来。否则 [1,2] 和 [2,1] 会从不同路径重复出现。 先写最小骨架。它只保留两个状态: ...

2026年5月3日 · 3 分钟 · map[name:Jeanphilo]

LeetCode 90:子集 II,从重复分支推出层内去重

题目要求 输入输出 输入:nums,长度 1 <= nums.length <= 10 元素范围:-10 <= nums[i] <= 10 nums 可能有重复元素 输出:返回所有不重复子集 顺序:结果顺序不限,但同一个值序列的子集只能出现一次 示例 输入:nums = [1,2,2] 输出:[[],[1],[1,2],[1,2,2],[2],[2,2]] 这篇只用 Python,从一个能跑但浪费的版本,一步一步过渡到排序 + 层内去重。 从 [1,2,2] 的重复分支开始 最小能暴露问题的例子是: nums = [1,2,2] 如果直接照搬 78. 子集 的模板,搜索树里会出现两条不同分支: 选择下标 1 的 2 -> [2] 选择下标 2 的 2 -> [2] 这两个分支路径不同,但值序列相同,最终答案重复。 所以这题真正新增的问题不是“会不会回溯”,而是: 怎样跳过重复分支,同时保留 [2,2] 这种合法答案? Step 1:先复用 78 的状态,看看哪里会坏 当前部分答案仍然需要 path;当前层仍然需要 start 控制只能往右选。 先写出 78 的核心版本: def dfs(start: int) -> None: res.append(path.copy()) for i in range(start, len(nums)): path.append(nums[i]) dfs(i + 1) path.pop() 这个版本在 nums 全部互不相同时是正确的。 ...

2026年5月3日 · 3 分钟 · map[name:Jeanphilo]

Attention-Based Seq2Seq:为什么会自然过渡到 Transformer

副标题 / 摘要 这篇文章专门解释一个关键过渡:为什么 fixed-length 的 seq2seq 很快会不够用,attention-based seq2seq 是怎么补上“按需读取源序列”这个能力的,以及这个思路为什么几乎会自然长成 Transformer。最后会收束到一份最小可运行的 PyTorch GRU + additive attention 实现。 从“苹果”为什么老翻不准开始 还是用这个最小翻译任务: src: <bos> I really love green apples <eos> tgt: <bos> 我 真的 喜欢 青 苹果 <eos> 当 decoder 走到要生成“苹果”这一步时,最理想的行为其实很明确: 它应该重点回头看源序列里的 apples 它可能顺手也看一眼 green 它不能只依赖一个已经被反复压缩过很多轮的最终隐藏状态 如果你用上一篇里那个最小 seq2seq: encoder 把整句读完 只把最后一个 hidden_enc 交给 decoder decoder 后面每一步都只靠这个固定长度状态和自己的历史 那么句子一长,这里就会出现一个很具体的问题: decoder 明明需要“现在按需去看源序列的某几个位置”,但 fixed-length seq2seq 只给了它“一次性打包好的整句摘要”。 这就是 attention-based seq2seq 出现的真实压力。 它不是为了“概念更高级”,而是因为 decoder 在每个时间步都需要重新决定自己该看源序列的哪里。 快速掌握地图 fixed-length seq2seq:encoder outputs -> 丢弃大部分,只保留 final hidden attention-based seq2seq:decoder step t -> 对所有 encoder outputs 打分 -> 加权求和得到 context_t 核心收益:不同目标位置可以读取不同源位置 仍然存在的限制:encoder 和 decoder 还是循环结构,时间上依然串行 通向 Transformer 的关键桥:decoder state 作为 query,encoder outputs 作为 memory 这篇文章重点深挖的两个概念 对齐分数与上下文向量:decoder 怎样在每一步决定“该看源序列哪里” 从 attention-based seq2seq 到 Transformer 的结构映射:哪些东西被保留了,哪些东西被替换了 大师级心智模型 fixed-length seq2seq 的核心假设是: ...

2026年4月23日 · 9 分钟 · map[name:Jeanphilo]