AlgoNote 题解:LeetCode 0318 最大单词长度乘积 —— 用位掩码把「两两判重」从 O(L²) 降到 O(1)
教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载本文是 AlgoNote算法通关手册对 LeetCode 0318. 最大单词长度乘积 的完整题解。题目本质上是一道「字符串集合求交」问题核心技巧是利用 26 个小写字母与 32 位整数的天然对应关系用位掩码Bitmask压缩每个单词的字符集合再用一次按位与运算完成任意两个单词是否含相同字符的判断。读完本文你将掌握位掩码压缩字符集合的建模方法、1 k与运算的落地写法、两重循环求最大值的实现以及基于「掩码去重 长度取最大」的优化思路。题目背景与出处本题在仓库题解体系中的位置题解文档docs/solutions/0300-0399/maximum-product-of-word-lengths.md同章节题解索引docs/solutions/0300-0399/index.md全量题目列表题号 标签 难度docs/00_preface/00_05_solutions_list.md按算法分类的练习清单位运算题目一栏docs/00_preface/00_06_categories_list.md此外同一道题目还以「LCR 005」编号收录在剑指 Offer 专项突击版中题解见 docs/solutions/LCR/aseY1I.md两篇题解的思路与代码完全一致。也就是说掌握本篇解法可以同时解决两个平台的题目。题目标签位运算、数组、字符串难度中等。题目大意给定一个字符串数组words其中每个字符串只包含英语小写字母a~z。要求计算当两个字符串words[i]和words[j]不包含相同字符时它们长度乘积的最大值。如果不存在任何一对不含相同字符的字符串返回0。示例与边界情况若words [abcw, baz, foo, bar, xtfn, abcdef]则abcw与xtfn不含相同字符长度乘积为4 × 4 16是全局最大值应返回16。若所有字符串两两之间都含有相同字符例如words [aaa, aa, a]则返回0。单个字符串长度、字符串数量都可能很大题目数据规模由力扣给出因此算法复杂度需要认真设计。核心难点与朴素思路本题唯一的难点在于如何快速判断任意两个字符串之间是否包含相同字符。最直接的做法是遍历第一个字符串的每个字符再遍历第二个字符串逐个比对是否有相同字符。这一步单次判重的时间复杂度为 $O(L_1 \times L_2)$其中 $L_1$、$L_2$ 为两个字符串的长度再加上两层循环枚举所有字符串对 $O(n^2)$整体复杂度高达 $O(n^2 \times L^2)$在数据规模较大时必然超时。思考优化方向题目给出一个非常强的约束——字符串只包含 26 种小写字母。这意味着每个单词的「字符集合」本质上是一个最多 26 个元素的集合完全可以用一个 26 位的二进制数来表示。而一个32位的int整数恰好有 32 个二进制位每一个二进制位都可以表示一种字符的有无。于是单词abc的字符集合{a, b, c}→ 二进制第 0、1、2 位为1其余为0两个单词是否有相同字符 → 对两个整数做按位与结果非0即有相同字符结果为0即无相同字符。这样单次「判重」操作就从字符级的两层遍历压缩成一条机器指令级的整数运算时间复杂度从 $O(L_1 \times L_2)$ 降为 $O(1)$。这种「用整数二进制位表示集合、用位运算代替集合运算」的手法正是位运算在状态压缩领域的经典应用。仓库的 docs/07_algorithm/07_06_bit_operation.md 章节系统讲解了按位与、按位或、左移等六种基础位运算及其常用操作如1 k置位、x y掩码提取本题就是该理论章节的典型实战习题。位掩码建模详解由于只有 26 种小写字母我们为每个字母分配一个固定的二进制位a对应第 0 位掩码值为1 0 1b对应第 1 位掩码值为1 1 2c对应第 2 位掩码值为1 2 4……z对应第 25 位掩码值为1 25。通用的位编号计算公式为1 (ord(ch) - ord(a))。其中ord(ch)返回字符的 ASCII 码ord(ch) - ord(a)把字母映射到0 ~ 25的编号1 k则把第k位置为1。遍历单词中的每个字符不断用按位或把这些位累加进一个整数最终这个整数就是该单词字符集合的位掩码abc→1 | 2 | 4 7二进制000...00111def→8 | 16 | 32 56二进制000...0111000。两个掩码做按位与7 56 0说明abc与def没有相同字符若掩码同为7的两个单词例如abc与cab7 7 7 ! 0说明有相同字符。26 种字符只需 26 位天然落在32位int的容量之内因此每个掩码都能用一个普通整型变量安全存放不需要任何额外的大整数类型。参考实现位掩码 双重循环以下代码完整继承自原题解并补充了逐行注释class Solution: def maxProduct(self, words: List[str]) - int: size len(words) # arr[i] 存储 words[i] 的字符集合位掩码初始全 0 arr [0 for _ in range(size)] # 第一轮为每个单词构建 26 位掩码 for i in range(size): word words[i] len_word len(word) for j in range(len_word): # 把第 (ord(word[j]) - ord(a)) 位置为 1并通过按位或累加 arr[i] | 1 (ord(word[j]) - ord(a)) # 第二轮两两比较掩码求长度乘积最大值 ans 0 for i in range(size): for j in range(i 1, size): # 按位与结果为 0 说明两个字符集合无交集 if arr[i] arr[j] 0: k len(words[i]) * len(words[j]) ans k if ans k else ans return ans代码关键点逐条拆解掩码构建1 (ord(word[j]) - ord(a))一次生成单字符对应的位掩码arr[i] | ...是arr[i] arr[i] | ...的简写用按位或把新字符位并入已有集合。由于同一字符多次出现只会反复置同一个位aaa的掩码和a完全一样这正符合「字符集合」语义。判重语句if arr[i] arr[j] 0:。在 Python 中按位与的优先级高于比较运算符因此该表达式等价于(arr[i] arr[j]) 0即「两个掩码按位与的结果为零」→「两单词无共同字符」。为可读性考虑建议实际编码时显式写成if (arr[i] arr[j]) 0:效果相同。对称性剪枝内层循环从j i 1开始只枚举i j的字符串对避免(i, j)与(j, i)重复计算。最大值维护用三目表达式ans k if ans k else ans维护历史最大值ans初始为0保证「没有合法字符串对」时正确返回0。复杂度分析阶段时间复杂度空间复杂度掩码构建$O(n \times L)$$n$ 为字符串个数$L$ 为单词平均长度$O(n)$ 用于arr数组两两比较$O(n^2)$每次比较是 $O(1)$ 的整数按位与$O(n)$ 复用arr数组整体时间复杂度 $O(n^2 n \times L)$空间复杂度 $O(n)$。相比朴素的 $O(n^2 \times L^2)$省去了判重时的字符级遍历这是本题收益最大的优化点。进阶优化掩码去重保留每种掩码的最大长度位掩码还有一个可利用的性质字符集合相同的单词其掩码完全相同例如abc、abcc、cba的掩码都是7。在求「长度乘积最大值」时对同一种掩码只有长度最长的那个单词才可能产生更大的乘积其余单词可以忽略。因此可以用一个哈希表字典把「掩码 → 该掩码下的最大单词长度」做压缩把参与两两比较的单词数量从 $n$ 降到「不同掩码数 $m$」当单词数量大、字符集合高度重复时收益明显。实现如下class Solution: def maxProduct(self, words: List[str]) - int: # 掩码 - 该掩码下最长的单词长度 mask_to_max_len {} for word in words: mask 0 for ch in word: mask | 1 (ord(ch) - ord(a)) if mask not in mask_to_max_len or len(word) mask_to_max_len[mask]: mask_to_max_len[mask] len(word) ans 0 masks list(mask_to_max_len.keys()) for i in range(len(masks)): for j in range(i 1, len(masks)): if (masks[i] masks[j]) 0: product mask_to_max_len[masks[i]] * mask_to_max_len[masks[j]] ans max(ans, product) return ans该优化版本与原版的核心建模一致mask | 1 (ord(ch) - ord(a))、mask1 mask2 0判无交集只是额外用字典压缩了冗余单词两轮循环都在更少的对象上进行。举一反三仓库中同类的位运算题目本题归类于仓库的「位运算」算法主题。以下题目分布在 docs/00_preface/00_06_categories_list.md 的位运算题目列表中与该题共用「用位表示状态、用位运算代替集合运算」的思想适合配套练习0338. 比特位计数统计0 ~ n每个数字二进制中1的个数可配合x (x - 1)技巧。0136. 只出现一次的数字利用异或运算a ^ a 0的性质找唯一出现一次的数。0371. 两整数之和只用位运算实现整数加法体会进位与异或的分工。0089. 格雷编码相邻编码只有一位不同的序列构造与二进制位密切相关。0190. 颠倒二进制位 与 0191. 位 1 的个数位运算基础操作练习。底层理论可回顾 docs/07_algorithm/07_06_bit_operation.md 中的六种基础位运算规则以及「将指定位设置为 1」x | (1 k)、「按位与取交集」等常用操作总结表。小结LeetCode 0318及 LCR 005的关键收获有三点建模遇到「元素种类少、需要频繁比较集合」的问题优先考虑用整数位掩码压缩集合26 个小写字母恰好对应 26 个二进制位32位int完全够用。判重maskA maskB 0一次运算即可断定两集合无交集把判重从 $O(L^2)$ 降到 $O(1)$。剪枝同掩码只保留最长单词用字典进一步压缩参与比较的单词数量。掌握位掩码这一招不仅在本题得分更能迁移到「状态压缩动态规划」「子集枚举」「集合求交」等一大类高频面试问题中。赞分享教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载相关推荐LeetCode 454. 四数相加 II 精讲两两分组 哈希表把 O(N⁴) 降到 O(N²)LeetCode 454. 四数相加 II 精讲两两分组 哈希表把 O N⁴ 降到 O N² 导读 本文以本仓库 problems/454.4 sum i文档教程知识库除自身以外数组的乘积LeetCode 0238题解前缀乘积 × 后缀乘积两次遍历法O(n) 时间 O(1) 空间除自身以外数组的乘积LeetCode 0238题解前缀乘积 × 后缀乘积两次遍历法O n 时间 O 1 空间 本文是「算法通关手册AlgoNote」教程文档知识库本地视频播放怎么弄wiliwili 掌机影音指南本地视频播放怎么弄wiliwili 掌机影音指南 先说个反直觉的Switch 离线看片卡不卡瓶颈往往不在播放器而在你那张 SD 卡的等级——U1 的卡配音视频桌面应用上一篇gh_mirrors/v41/v4中的渐进式增强策略从基础到高级体验下一篇Uber Go 编码规范字符串与字节切片的高效转换创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

网盘下载慢怎么办:6款高速下载工具实测对比,直链解析工具这样选

网盘下载慢怎么办:6款高速下载工具实测对比,直链解析工具这样选

网盘下载慢怎么办:6款高速下载工具实测对比,直链解析工具这样选 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 /…

2026/10/9 7:31:27 阅读更多 →
扁平化嵌套列表迭代器:AlgoNote 0341 题解,用栈实现 NestedInteger 的惰性展开

扁平化嵌套列表迭代器:AlgoNote 0341 题解,用栈实现 NestedInteger 的惰性展开

教程文档知识库 【免费下载链接】AlgoNote ⛽️「算法通关手册」:从零开始的「算法与数据结构」学习教程,200 道「算法面试热门题目」,1000 道「LeetCode 题目解析」,持续更新中! 项目地址: https://gitcod…

2026/10/9 4:18:15 阅读更多 →
go-questions 深度解析:Go 垃圾回收(GC)的认识——从基本概念到三色标记与写屏障

go-questions 深度解析:Go 垃圾回收(GC)的认识——从基本概念到三色标记与写屏障

文档教程 【免费下载链接】go-questions 📖 Go 程序员面试笔试宝典 | 从问题切入,串连 Go 语言相关的所有知识,融会贯通。 https://golang.design/go-questions 项目地址: https://gitcode.com/gh_mirrors/go/go-questions 点击查…

2026/10/9 5:06:02 阅读更多 →

最新新闻

diskinfo监控RAID健康状态保障TensorFlow数据安全

diskinfo监控RAID健康状态保障TensorFlow数据安全

1. 项目背景与核心问题拆解1.1 这个标题到底在说什么先把标题拆开看:diskinfo、RAID阵列健康状态、TensorFlow数据安全。三个词串起来,其实描述的是一个非常具体、也非常容易被忽视的运维场景——跑深度学习训练任务的服务器,底层磁盘阵列的健…

2026/10/9 7:56:25 阅读更多 →
第57章 巽•巽顺 顺其自然

第57章 巽•巽顺 顺其自然

2042年初春的某个下午,悦儿在Courant研究所的走廊里遇到了一位从欧洲来的访问学者。那人她以前在会议上见过一两次,不算熟,但也不算完全陌生。他们站在走廊的窗边聊了几句关于最近发表的某篇论文的内容,然后那个人忽然换了一个话题…

2026/10/9 7:56:25 阅读更多 →
MySQL操作相关知识点个人总结

MySQL操作相关知识点个人总结

一、数据库创建相关1.编码集创建数据库的时候,有两个编码集:数据库编码集,数据库未来存储数据的编码格式数据库校验集,数据库进行字段比较使用的编码采用什么编码集决定存取数据时采用什么编码,操作和编码必须是一致的…

2026/10/9 7:56:25 阅读更多 →
装饰模式详解:不靠继承也能动态扩展对象功能(含可运行代码 + 与继承/适配器辨析)

装饰模式详解:不靠继承也能动态扩展对象功能(含可运行代码 + 与继承/适配器辨析)

一、装饰模式是什么 装饰模式动态地给一个对象添加额外的职责。就增加功能而言,装饰模式相比生成子类(继承)更为灵活。 核心思想:把"核心功能"和"附加功能"分开,附加功能做成一个个"装饰器&q…

2026/10/9 7:56:25 阅读更多 →
函数递归知识

函数递归知识

函数递归知识 文章目录函数递归知识一.什么是递归(一)递归的思想(二)递归的限制条件二.递归举例(一)举例1:求n的阶乘1.分析和代码实现2.画图推演(二)举例2:顺…

2026/10/9 7:56:24 阅读更多 →
数据库课程设计模板:学生成绩管理系统表结构与SQL实战

数据库课程设计模板:学生成绩管理系统表结构与SQL实战

简介:这份资源是面向高校数据库课程设计场景的学生成绩管理系统模板文档,适合正在完成数据库课设、需要参考完整设计流程与报告结构的本科生或自学者。文档以Microsoft SQL Server 2000为设计环境,围绕需求分析、概念模型、逻辑与物理结构设计…

2026/10/9 7:55:24 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →