Hot100:相交链表(Intersection of Two Linked Lists)双指针换头 O(1) 空间 ACERS 解析

副标题 / 摘要 相交链表的关键不是比较值,而是比较“节点引用/地址”。本文用 ACERS 结构把朴素哈希解法、长度对齐解法与最常用的“双指针换头”模板讲清楚,并给出多语言可运行实现(不修改链表、无环前提)。 预计阅读时长:10~14 分钟 标签:Hot100、链表、双指针 SEO 关键词:相交链表, 双指针换头, O(1) 空间, LeetCode 160, Intersection of Two Linked Lists 元描述:双指针分别走完 A 与 B 后交换起点,保证在 m+n 步内相遇于交点或同时到达 null;O(m+n)/O(1) 且不修改链表结构。 A — Algorithm(题目与算法) 题目还原 给你两个单链表的头节点 headA 和 headB,请你找出并返回两个单链表相交的起始节点。 如果两个链表不存在相交节点,返回 null。 补充约束: 题目数据保证整个链式结构中不存在环 返回结果后,链表必须保持其原始结构(不允许修改链表) 输入输出 名称 类型 描述 headA ListNode 链表 A 的头结点 headB ListNode 链表 B 的头结点 返回 ListNode / null 相交起始节点(同一节点对象),或 null 示例 1(图示场景) A: a1 -> a2 -> c1 -> c2 -> c3 B: b1 -> b2 -> b3 -> c1 -> c2 -> c3 输出: c1(返回节点引用,不是数值) 示例 2(不相交) A: 1 -> 2 -> 3 B: 4 -> 5 输出: null 目标读者 刷 Hot100,希望把链表双指针模板一次性吃透的学习者 经常把“节点值相等”误当作“节点相同”的初中级开发者 需要在工程里处理共享链式结构(共享后缀/共享节点)的工程师 背景 / 动机 这题看似简单,但它强迫你分清三个概念: ...

2026年2月1日 · 10 分钟 · map[name:Jeanphilo]

Hot100:搜索二维矩阵 II(Search a 2D Matrix II)右上角阶梯搜索 O(m+n) ACERS 解析

副标题 / 摘要 这题的关键不是二分,而是利用“行列都单调”的结构,从**右上角(或左下角)**像走楼梯一样移动:每一步都能排除一整行或一整列,从而把复杂度降到 O(m+n)。 预计阅读时长:10~13 分钟 标签:Hot100、矩阵、单调性、指针 SEO 关键词:搜索二维矩阵 II, 单调矩阵查找, 右上角搜索, O(m+n), LeetCode 240 元描述:在行列均升序的矩阵中搜索 target:从右上角阶梯式移动,每步排除一行或一列,O(m+n)/O(1) 解法与多语言实现。 目标读者 刷 Hot100,希望掌握“二维单调结构剪枝”模板的学习者 写过二分但总在二维问题里迷路的中级开发者 在工程中需要查询/裁剪/定位二维单调表格的工程师 背景 / 动机 二维表在工程里很常见:费率表、校准表、阈值表、网格配置表等。 当一个表满足“横向递增 + 纵向递增”的 二维单调(monotone matrix) 特性时,很多查询不需要 O(mn) 全扫。 这题就是经典入门:用单调性做剪枝,把搜索降成线性级别。 核心概念 概念 含义 在本题的作用 二维单调矩阵 行升序、列升序 保证“比较一次就能排除一行/列” 右上角起点 右上角元素:左边更小、下边更大 决策方向天然明确 剪枝 排除不可能包含 target 的行/列 每步减少搜索空间 O(1) 额外空间 只用 i/j 指针 适合大矩阵与性能场景 A — Algorithm(题目与算法) 题目还原 给定一个 m x n 矩阵 matrix 和一个目标值 target。矩阵满足: ...

2026年2月1日 · 7 分钟 · map[name:Jeanphilo]

Hot100:螺旋矩阵(Spiral Matrix)边界收缩模拟 ACERS 解析

副标题 / 摘要 “顺时针螺旋遍历”看似只是打印顺序,实则考验你对边界与循环不变量的掌控。本文用 ACERS 结构给出可直接复用的边界收缩模板,并给出多语言可运行实现。 预计阅读时长:12~15 分钟 标签:Hot100、矩阵、模拟、边界收缩 SEO 关键词:Hot100, Spiral Matrix, 螺旋矩阵, 顺时针螺旋遍历, 边界收缩, LeetCode 54 元描述:用边界收缩法输出矩阵的顺时针螺旋序列,包含推导、工程场景、复杂度对比与多语言代码。 目标读者 正在刷 Hot100、想把“矩阵模拟题”沉淀成模板的同学 对边界条件容易写错、希望提升代码稳健性的中级开发者 做可视化/栅格数据处理/网格路径相关任务的工程师 背景 / 动机 矩阵类题目最容易“写得出来,但写不对”: 多一层循环、多一个边界判断,就可能在单行/单列、奇偶层数时出错或重复输出。 螺旋遍历是一个很好的训练题:它逼你把 循环不变量(哪些行列还没被处理)和 边界收缩(每处理完一条边就把边界往里缩)描述清楚,代码才能既短又不炸。 核心概念 边界(Boundaries):用 top/bottom/left/right 表示当前还未处理的矩形外框 层(Layer):每次循环处理一圈外框(上边、右边、下边、左边) 收缩(Shrink):每处理完一条边就移动对应边界:top++、right--、bottom--、left++ 循环不变量:始终保证未输出区域是 top..bottom × left..right A — Algorithm(题目与算法) 题目还原 给你一个 m 行 n 列的矩阵 matrix,请按照 顺时针螺旋顺序,返回矩阵中的所有元素。 输入输出 名称 类型 描述 matrix int[][] m × n 的矩阵 返回 int[] 按顺时针螺旋顺序输出的所有元素 示例 1(自拟) matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] 输出: [1, 2, 3, 6, 9, 8, 7, 4, 5] 示例 2(自拟) matrix = [ [ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12] ] 输出: [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7] C — Concepts(核心思想) 思路推导:从“标记访问”到“边界收缩” 朴素思路:方向数组 + visited 标记 从 (0,0) 出发按右/下/左/上转向;走到越界或已访问就转向。 优点:直观 缺点:需要 m×n 的 visited,空间浪费;代码更容易写出越界/重复判断 关键观察:螺旋遍历 = 一圈圈“剥洋葱” 每一圈只需要处理四条边:上边一行、右边一列、下边一行、左边一列。 处理完外圈,就把边界往里缩,问题规模变小。 方法选择:边界收缩(O(1) 额外空间) 用四个指针维护未处理矩形:top, bottom, left, right。 每轮输出四条边(注意边界交叉时跳过),直到 top > bottom 或 left > right。 ...

2026年2月1日 · 9 分钟 · map[name:Jeanphilo]

Hot100:旋转图像(Rotate Image)转置 + 行反转实现原地 90 度旋转 ACERS 解析

副标题 / 摘要 旋转图像的核心不是“算新坐标”,而是把映射拆成两个可原地执行的操作:转置(transpose)+ 反转每一行(reverse rows)。本文按 ACERS 模板给出从朴素解到原地解的推导、常见坑与多语言可运行实现。 预计阅读时长:10~14 分钟 标签:Hot100、矩阵、原地、转置 SEO 关键词:旋转图像, Rotate Image, 原地旋转 90 度, 转置, 行反转, LeetCode 48 元描述:顺时针原地旋转 n×n 矩阵 90 度:转置 + 行反转模板解;含思路推导、复杂度对比、工程迁移与多语言实现。 目标读者 刷 Hot100,想把“矩阵原地技巧”整理成可复用模板的学习者 需要在工程里处理二维网格(图像/棋盘/地图/热力图)变换的开发者 对空间敏感,希望避免额外矩阵拷贝的工程师 背景 / 动机 在很多场景里,“旋转”是高频操作: 图像增强、棋盘/地图方向变换、传感器方向校正、UI 表格视图旋转等。 如果每次旋转都新建一个矩阵,空间开销是 O(n^2),在大矩阵或高频调用时会非常“吃内存”,甚至触发 GC/内存抖动。 因此这题的关键约束是:必须原地(in-place)完成 90 度旋转。 核心概念 概念 含义 为什么重要 坐标映射 旋转后的新坐标与旧坐标之间的关系 让你知道“最终要变成什么” 转置(Transpose) matrix[i][j] 与 matrix[j][i] 交换 原地可做、且能把行列关系对齐 行反转(Reverse Row) 把每一行左右翻转 与转置组合后刚好等价于顺时针 90 度 原地算法 只用常数额外空间完成变换 适合大矩阵与性能场景 A — Algorithm(题目与算法) 题目还原 给定一个 n x n 的二维矩阵 matrix 表示图像。请将图像 顺时针旋转 90 度。 要求 原地修改 matrix,不要使用另一个矩阵。 ...

2026年2月1日 · 7 分钟 · map[name:Jeanphilo]

矩阵置零:用首行首列做标记实现原地 O(1) 空间(LeetCode 73)

副标题 / 摘要 “矩阵置零”是典型的二维标记传播问题:某个位置为 0,会影响整行整列。本文用 ACERS 结构讲清楚为什么不能直接改、如何用首行首列做标记实现原地 O(1) 额外空间,并给出多语言可运行代码。 预计阅读时长:12~15 分钟 标签:矩阵、原地算法、标记位 SEO 关键词:矩阵置零, 原地 O(1) 空间, 首行首列标记, LeetCode 73 元描述:用首行首列作标记位,原地将含 0 的行与列全部置零;包含推导、复杂度对比、工程迁移与多语言实现。 目标读者 刷 LeetCode,想把“二维数组原地技巧”沉淀成稳定模板的同学 需要在工程里做二维网格/表格/矩阵数据清洗与传播标记的开发者 对空间优化敏感(嵌入式、性能场景、内存受限)的工程师 背景 / 动机 二维数据在工程里到处都是:表格、图像、传感器网格、关联矩阵…… “某个单元格触发规则 -> 影响整行整列”这种联动,本质就是 行列传播(row/col propagation)。 这题额外要求“原地”,逼你掌握一个非常通用的技巧:用数据结构本身的某些位置当作标记位,避免额外内存。 核心概念 传播标记:发现 0 后,不是立刻改整行整列,而是先记录“哪些行/列要被清零” 原地(in-place):只允许 O(1) 额外空间(不算输入矩阵本身) 标记位复用:把 matrix[0][j] 当作“第 j 列要清零”的标记,把 matrix[i][0] 当作“第 i 行要清零”的标记 首行/首列特判:首行/首列既是数据又是标记位,因此需要单独用两个布尔量记录它们是否本来就该清零 A — Algorithm(题目与算法) 题目还原 给定一个 m x n 矩阵 matrix:如果某个元素为 0,则将该元素所在的 整行 与 整列 的所有元素都设置为 0。 要求 原地修改 matrix(通常不需要返回值)。 ...

2026年2月1日 · 10 分钟 · map[name:Jeanphilo]

Windows 双网络分流:公司 WiFi 走内网,手机 USB 共享走外网

标题 Windows 双网络分流:公司 WiFi 走内网,手机 USB 共享走外网 副标题 / 摘要 你想访问公司内网(例如 192.168.x.x 的 Gitlab / 内部 API / 数据库),同时让浏览网页、下载等互联网流量走手机热点。 最稳的做法是:公司 WiFi 只负责内网,手机 USB 网络共享作为默认外网出口,并用 Windows 的路由优先级(跃点数/metric)把流量分开。 目标读者 需要访问公司内网服务,但不想让外网走公司出口的开发者/运维 经常在公司/外出之间切换网络,希望“插手机就能分流”的同学 Windows 10/11 用户(公司 WiFi + 手机 USB 共享) 背景 / 动机 当你同时连上: 公司 WiFi(内网:192.168.x.x) 手机 USB 网络共享(外网:互联网) Windows 会出现两个“默认网关”。如果不配置,系统可能随机抢路由,导致: 外网有时走公司(慢/受限) 内网有时走手机(根本不通) VPN/虚拟网卡(如 Tailscale、SSL VPN、WSL)插一条路由就更混乱 这篇文章的目标是把行为固定下来: 外网默认走手机 内网稳定走公司 WiFi 核心概念 默认路由(Default route):0.0.0.0/0,没有更具体匹配时走它(通常就是“上网出口”)。 最长前缀匹配:越具体的网段路由优先(例如 192.168.1.0/24 会优先于 0.0.0.0/0)。 跃点数 / Metric:当有多条可用路径时,Windows 选择 metric 更小 的那条。 接口跃点数(Interface metric):网卡层面的优先级,影响默认路由选择。 静态路由(Static route):手动指定某个网段必须走哪个网关(可选但更稳)。 A — Algorithm(题目与算法) 题目还原 电脑连接公司 WiFi(只负责访问公司内网),手机用 USB 网络共享(只负责上互联网),怎么配置才能稳定分流? ...

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

WireGuard Split Tunnel 实战:手机热点上外网,同时访问公司内网

标题 WireGuard Split Tunnel 实战:手机热点上外网,同时访问公司内网 副标题 / 摘要 你想在外网(手机热点)正常上网,同时访问公司内网(192.168.x.x)服务。 最干净的方式是:外网默认走手机热点,只有内网网段走 WireGuard(Split Tunnel)。 目标读者 需要在外网访问公司内网服务(Gitlab/内部 API/数据库)的开发者 公司内网没有官方 VPN,或现有 VPN 体验差 希望“分流”:外网不走公司出口,内网安全可控 背景 / 动机 很多公司内网服务只在私网开放(如 192.168.1.0/24)。 当你在外面用手机热点上网时: 外网访问没问题 但内网地址不可达 如果你把电脑同时连两条网络(公司 WiFi + 手机热点),“能用但不干净”: 路由/DNS 冲突、稳定性差、切换成本高。 WireGuard 的价值在于: 只打通你需要的内网网段(Split Tunnel) 外网仍走你自己的手机出口 连接快、配置简单、性能好 核心概念 WireGuard:现代 VPN 协议与实现,配置简洁、性能优秀。 Peer:对端节点(客户端/服务器)。 AllowedIPs(关键):决定哪些流量走 VPN。 Split Tunnel(分流):AllowedIPs 只写内网网段,不接管默认路由。 NAT / 端口映射:服务器在内网(192.168.*)时,外网直连需要网关转发 UDP 端口。 思维推导(从“想要双网”到“正确分流”) 需求:公司内网访问 + 手机热点上外网。 朴素解:同时连两张网卡,靠系统自动选路由 → 不稳定。 关键观察:你的目标不是“同时连两张网”,而是“只让内网走公司通道”。 方法选择:WireGuard Split Tunnel:仅路由 192.168.x.x 走 VPN。 约束:WireGuard 需要一个外网可达的 Endpoint;如果公司服务器在 NAT 后面,需要端口映射或中转方案。 A — Algorithm(题目与算法) 题目还原 电脑连手机热点上网,但还能访问公司内网(如 192.168.1.0/24)。 ...

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

Tailscale 子网路由实战:外网访问公司内网的最稳方案

标题 Tailscale 子网路由实战:外网访问公司内网的最稳方案 副标题 / 摘要 当公司内网没有公网 IP 时,Tailscale 的子网路由是最省事、最稳定的方案。 本文给出完整的部署步骤、验证方法与排错清单,适合直接落地。 目标读者 需要在外网访问公司内网服务的开发者/运维 公司没有官方 VPN,且内网在 NAT 后面 希望实现“外网走手机热点、内网走 VPN”的分流需求 背景 / 动机 很多公司内网服务器只有 192.168.x.x 等私有地址, 外网无法直接访问,传统 WireGuard 需要公网 IP 或端口映射。 Tailscale 基于 WireGuard,但可以穿透 NAT, 无需公网入口即可实现安全访问,是更工程化的解法。 核心概念 子网路由(Subnet Router):让一台内网机器“代理”整个内网段 Split Tunnel(分流):只有内网流量走 VPN,外网流量不变 Advertise Routes:向 tailnet 宣告你能到达的内网网段 Approve Routes:在控制台批准路由才能生效 实践指南 / 步骤(完整落地) 以下以公司内网 192.168.1.0/24 为例,你可替换成自己的网段。 1)在公司内网服务器安装 Tailscale curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up 登录后,服务器会出现在控制台设备列表中。 2)将服务器设置为子网路由 sudo tailscale up --advertise-routes=192.168.1.0/24 3)到控制台批准路由(必须) 打开控制台: ...

2026年1月29日 · 2 分钟 · map[name:Jeanphilo]

一台电脑同时连公司内网和手机外网:双网络分流实战

标题 一台电脑同时连公司内网和手机外网:双网络分流实战 副标题 / 摘要 想用公司内网访问内部服务,又希望互联网走手机热点? 本文给出 3 套可落地方案:USB 共享、双网卡分流、VPN Split Tunnel, 并提供 Windows/macOS/Linux 的实操步骤。 目标读者 需要访问公司内网,但不想走公司外网出口的开发者/运维 想在一个电脑上同时使用两条网络链路的技术人员 需要稳定分流、减少网络切换成本的同学 背景 / 动机 你希望达到的效果是: 公司内网服务(Gitlab、内网 API、数据库)走公司网络 外网互联网(搜索、下载、第三方服务)走手机热点 但普通电脑默认只能有一个默认网关, 所以要么全部走公司网,要么全部走手机网。 这也是需要“分流”的原因。 核心概念 网卡(NIC):每条网络连接对应一个网卡(WiFi、USB、网线) 默认路由:系统不知道去哪就走默认网关 最长前缀匹配:更具体的网段路由会优先生效 分流(Split Routing / Split Tunnel):内网走公司,外网走手机 实践指南 / 步骤 下面按稳定性从高到低给出三种方案: 方案 A:公司内网 WiFi + 手机 USB 共享(最稳定) 适用场景:只有一张 WiFi 网卡,想要最省事的分流方式。 连接公司 WiFi(内网) 手机开启 USB 共享网络,连接电脑 系统通常会把 USB 网络作为默认外网 优点:稳定、无需额外硬件; 缺点:需要 USB 连接手机。 方案 B:双 WiFi(USB 无线网卡) 适用场景:必须同时连接两个 WiFi。 ...

2026年1月29日 · 2 分钟 · map[name:Jeanphilo]

请求日志一定要带 RequestId 吗?Python 成熟实践与落地指南

标题 请求日志一定要带 RequestId 吗?Python 成熟实践与落地指南 副标题 / 摘要 几乎所有“请求相关”的日志都应该带 requestId,但要通过自动注入而不是手工拼接。 本文给出 Python 成熟做法、工程场景与与 tracing 的关系,帮你真正落地。 目标读者 初学者:第一次处理线上问题,不懂为什么日志要串 requestId。 中级开发者:需要一套可复制的 Python 日志注入方案。 团队负责人:想建立统一的日志与追踪规范。 背景 / 动机 当系统出现错误时,最常见的现场是: “某个时间点报错了,但不知道是哪次请求导致的。” 如果所有“请求相关日志”都有 requestId,你就能一条链串起来: 从入口 → DB → RPC → 异常,一次请求的关键路径一眼可见。 在微服务/多进程环境里,requestId 更是日志协作的最低门槛。 核心概念 requestId:一次请求的唯一编号,用于日志串联与快速定位。 trace_id / span_id:分布式追踪中的链路标识(trace)与步骤标识(span)。 上下文传播:跨线程 / 协程 / 服务传递 requestId 或 trace。 自动注入:通过 middleware + logging filter,在日志里自动带 requestId。 思维推导(从朴素到工程可用) 朴素做法:每条日志手动写 request_id,很快遗漏、重复、维护成本高。 痛点暴露:一次请求会跨多个函数/协程/库层,手写方式不可控。 关键观察:requestId 本质是“请求上下文”,应由框架统一注入。 方法选择:在入口生成 requestId → 传入上下文 → logging 自动注入。 正确性理由:上下文随请求自然传播,日志格式统一且不侵入业务代码。 A — Algorithm(题目与算法) 题目还原 “是不是每一条日志都应该带 requestId?” ...

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