资讯动态

LeetCode 面试题 01.02 Check Permutation 判定是否互为字符重排:计数与排序双解法全解析(doocs/leetcode 多语言实现)

发布时间:2026/9/30 1:50:44 来源:尧图企业网站定制
示例工程教程【免费下载链接】leetcodeLeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer第 2 版》、《程序员面试金典第 6 版》题解项目地址https://gitcode.com/doocs/leetcode点击查看免费下载本文以 doocs/leetcode 开源仓库中的 lcci/01.02.Check Permutation/README_EN.md 为核心系统讲解《程序员面试金典》面试题 01.02「判定是否互为字符重排」的完整解法哈希计数法数组/哈希表与排序法并给出 Python、Java、C、Go、TypeScript、Rust、JavaScript、Swift 八种语言的仓库级实现以及时间/空间复杂度对比与边界情况讨论。读完本文你将掌握两个字符串互为排列问题的判定原理、两种解法的取舍依据以及如何在多语言工程中落地这套标准解法。题目描述与约束原题英文题面 / 中文题面Given two strings, write a method to decide if one is a permutation of the other.给定两个字符串s1和s2请编写一个程序确定其中一个字符串的字符重新排列后能否变成另一个字符串。示例输入输出说明s1 abc,s2 bcatruebca是abc的字符重排s1 abc,s2 badfalse字符集合不一致约束条件Note0 len(s1) 1000 len(s2) 100关键约束提示本题测试用例中的所有字符串仅包含小写字母这直接决定了方法一可以使用长度为26的定长数组充当哈希表将计数空间压缩到常量级。核心思路互为排列的本质两字符串互为排列permutation当且仅当两者的字符多重集合multiset完全相同——即每个字符的出现次数逐一相等。据此可以立刻得出两条推论长度不等必为 false若len(s1) ! len(s2)二者的字符总数不同直接返回false无需任何统计。枚举全排列是错误方向若枚举s1的全部排列再与s2逐一比较代价为阶乘级远超题目规模所需。正确方向是核对字符频次。围绕核对频次业界与本题仓库给出了两条主线解法方法一哈希计数数组 / 哈希表——时间最优O(n)方法二排序比较——实现最简O(n log n)且不依赖字符集规模假设。下面分别展开每种方法均给出仓库中Solution.*与Solution2.*的真实源码实现。方法一哈希计数数组或哈希表算法流程比较两字符串长度不等则直接返回false用一个数组或哈希表统计s1中每个字符的出现次数遍历s2每遇到一个字符就将其对应计数减一若某字符减一后的计数小于0说明该字符在s2中出现的次数多于在s1中的次数两串频次不一致返回false遍历完s2仍无异常返回true。为什么减一后小于 0即判负两串长度相同若s2中某字符出现次数超过s1必然会有另一字符在s2中出现次数少于s1最终计数数组不可能全部归零因此在扫描途中一旦出现负数即可提前终止。计数容器的选择字符集场景推荐容器说明仅含小写字母本题int[26]定长数组空间O(1)下标映射c - a性能最佳字符集较大或不确定Unicode 等哈希表如 PythonCounter、TS/JS 对象、RustHashMap空间随实际出现字符数增长通用性强Python3 实现仓库文件Solution.pyclass Solution: def CheckPermutation(self, s1: str, s2: str) - bool: return Counter(s1) Counter(s2)Python 直接利用collections.Counter构造两个字符计数多重集合比较相等即判定结果。注意Counter相等比较对缺失键与零值计数视为等价例如Counter({a: 0}) Counter()为True恰好契合频次一致的语义。Java 实现仓库文件Solution.javaclass Solution { public boolean CheckPermutation(String s1, String s2) { if (s1.length() ! s2.length()) { return false; } int[] cnt new int[26]; for (char c : s1.toCharArray()) { cnt[c - a]; } for (char c : s2.toCharArray()) { if (--cnt[c - a] 0) { return false; } } return true; } }char参与算术运算时自动提升为intc - a将a~z映射到下标0~25。C 实现仓库文件Solution.cppclass Solution { public: bool CheckPermutation(string s1, string s2) { if (s1.size() ! s2.size()) { return false; } int cnt[26]{}; for (char c : s1) { cnt[c - a]; } for (char c : s2) { if (--cnt[c - a] 0) { return false; } } return true; } };int cnt[26]{}值初始化将全部元素置零。Go 实现仓库文件Solution.gofunc CheckPermutation(s1 string, s2 string) bool { if len(s1) ! len(s2) { return false } cnt : make([]int, 26) for _, c : range s1 { cnt[c-a] } for _, c : range s2 { if cnt[c-a]--; cnt[c-a] 0 { return false } } return true }注意 Go 中for _, c : range遍历字符串时c为rune但本题仅含小写字母c-a的差值恒为非负整数可直接作下标。TypeScript 实现仓库文件Solution.tsfunction CheckPermutation(s1: string, s2: string): boolean { if (s1.length ! s2.length) { return false; } const cnt: Recordstring, number {}; for (const c of s1) { cnt[c] (cnt[c] || 0) 1; } for (const c of s2) { if (!cnt[c]) { return false; } cnt[c]--; } return true; }TS/JS 无原生定长数组计数习惯采用Recordstring, number哈希对象(cnt[c] || 0) 1处理首次出现的键扫描s2时!cnt[c]捕获计数为0或缺失的情况。Rust 实现仓库文件Solution.rsimpl Solution { pub fn check_permutation(s1: String, s2: String) - bool { if s1.len() ! s2.len() { return false; } let mut cnt vec![0; 26]; for c in s1.chars() { cnt[(c as usize - a as usize)] 1; } for c in s2.chars() { let index c as usize - a as usize; if cnt[index] 0 { return false; } cnt[index] - 1; } true } }Rust 中char先转usize再作下标扫描s2时用cnt[index] 0代替负数判断vec![0; 26]内为无符号计数语义同样能提前判负。JavaScript 实现仓库文件Solution.js/** * param {string} s1 * param {string} s2 * return {boolean} */ var CheckPermutation function (s1, s2) { if (s1.length ! s2.length) { return false; } const cnt {}; for (const c of s1) { cnt[c] (cnt[c] || 0) 1; } for (const c of s2) { if (!cnt[c]) { return false; } cnt[c]--; } return true; };Swift 实现仓库文件Solution.swiftclass Solution { func CheckPermutation(_ s1: String, _ s2: String) - Bool { if s1.count ! s2.count { return false } var cnt Int for char in s1 { cnt[Int(char.asciiValue! - Character(a).asciiValue!)] 1 } for char in s2 { let index Int(char.asciiValue! - Character(a).asciiValue!) if cnt[index] 0 { return false } cnt[index] - 1 } return true } }Swift 通过asciiValueUInt8相减得到0~25的下标。复杂度分析方法一时间复杂度O(n)其中n为字符串长度两串长度相等时两次线性扫描一次统计、一次核对。空间复杂度O(C)C为字符集大小。本题仅含小写字母C 26因此数组实现的空间为常量O(1)若用哈希表则空间随实际出现的不同字符数增长最坏仍为O(C)。方法二排序算法流程将s1与s2各自按字典序lexicographical order排序比较排序后的两串是否相等相等即互为排列否则不是。原理排序是多重集合的规范化canonical form——同一多重集合的任意排列排序后得到相同序列不同多重集合排序后必不相同。与计数法相比排序法不假设字符集规模实现代码更短代价是时间升至O(n log n)。Python3 实现仓库文件Solution2.pyclass Solution: def CheckPermutation(self, s1: str, s2: str) - bool: return sorted(s1) sorted(s2)Java 实现仓库文件Solution2.javaclass Solution { public boolean CheckPermutation(String s1, String s2) { char[] cs1 s1.toCharArray(); char[] cs2 s2.toCharArray(); Arrays.sort(cs1); Arrays.sort(cs2); return Arrays.equals(cs1, cs2); } }注意使用Arrays.equals比较字符数组内容引用比较的是地址。C 实现仓库文件Solution2.cppclass Solution { public: bool CheckPermutation(string s1, string s2) { ranges::sort(s1); ranges::sort(s2); return s1 s2; } };C 版本采用 C20 的std::ranges::sort就地排序后直接比较字符串。Go 实现仓库文件Solution2.gofunc CheckPermutation(s1 string, s2 string) bool { cs1, cs2 : []byte(s1), []byte(s2) sort.Slice(cs1, func(i, j int) bool { return cs1[i] cs1[j] }) sort.Slice(cs2, func(i, j int) bool { return cs2[i] cs2[j] }) return string(cs1) string(cs2) }Go 将字符串转[]byte排序后转回string比较本题仅 ASCII 小写字母[]byte安全。TypeScript 实现仓库文件Solution2.tsfunction CheckPermutation(s1: string, s2: string): boolean { return [...s1].sort().join() [...s2].sort().join(); }Rust 实现仓库文件Solution2.rsimpl Solution { pub fn check_permutation(s1: String, s2: String) - bool { let mut s1: Vecchar s1.chars().collect(); let mut s2: Vecchar s2.chars().collect(); s1.sort(); s2.sort(); s1 s2 } }JavaScript 实现仓库文件Solution2.js/** * param {string} s1 * param {string} s2 * return {boolean} */ var CheckPermutation function (s1, s2) { return [...s1].sort().join() [...s2].sort().join(); };Swift 实现仓库文件Solution2.swiftclass Solution { func CheckPermutation(_ s1: String, _ s2: String) - Bool { let s1 s1.sorted() let s2 s2.sorted() return s1 s2 } }复杂度分析方法二时间复杂度O(n × log n)由两次排序主导n为字符串长度。空间复杂度O(n)取决于所用排序实现如归并排序的辅助空间部分语言对短数组采用就地插入排序但最坏仍视为O(n)。两种方法对比与选型维度方法一哈希计数方法二排序时间复杂度O(n)O(n × log n)空间复杂度O(C)本题C26即O(1)O(n)对字符集假设定长数组版本依赖已知字符集哈希表版无假设无任何假设实现长度略长需显式计数逻辑极短一行核心逻辑适用场景追求线性时间、字符集已知如仅小写字母代码简洁优先、字符集不确定、n较小实践建议面试场景优先给出方法一并说明26数组的由来题目仅含小写字母随后可追问若字符集包含 Unicode 如何处理此时切换哈希表版或排序法即可覆盖。若两串长度不等两种方法都可先做长度短路排序法虽然代码里未显式判断但排序后比较仍正确只是略多开销。仓库源码结构说明在 doocs/leetcode 仓库中本题目录 lcci/01.02.Check Permutation 下并存两套独立源码文件Solution.*8 个文件方法一哈希计数实现对应 README 的Solution 1Solution2.*8 个文件方法二排序实现对应 README 的Solution 2。涉及的编程语言包括 Python3、Java、C、Go、TypeScript、Rust、JavaScript、Swift且各语言的独立文件与 README_EN.md 中展示的代码完全一致可直接对照阅读或本地运行验证。该目录隶属于仓库的 lcci 题解专区《程序员面试金典》第 6 版题目元数据frontend_id、标题、难度等统一收录于 lcci/lcci.json本题difficulty标记为Easy简单。边界情况与扩展讨论边界用例验证输入期望判定路径,true长度相等、计数均为零返回truea,atrue长度相等频次一致abc,abcdfalse长度不等方法一直接短路aab,abatrue频次一致a×2, b×1互为重排aab,abbfalse频次不一致a与b数量对调扩展点 1——字符集放大若输入扩展为任意 ASCII 可打印字符95 个或 Unicode可把定长数组改为int[128]、int[256]或直接换用哈希表各语言Solution.*的哈希表版本思路通用。扩展点 2——内存受限变体若要求O(1)额外空间且字符集极大可在长度相等前提下先排序后比较原地排序但时间升为O(n log n)——这正是方法二的适用场景。扩展点 3——相关题目迁移该频次核对模板在同类题目中复用度高例如统计异位词anagram分组、判断字符串是否可通过重排变为回文等核心都是先构建字符多重集合再做一次核对。总结面试题 01.02「判定是否互为字符重排」的核心结论可浓缩为一句互为排列 ⇔ 字符多重集合相同。工程上两条路线——O(n)的哈希计数与O(n log n)的排序比较——覆盖了字符集已知求最快与实现最简求通用两类诉求。doocs/leetcode 仓库为该题提供了 8 种语言的完整双解法源码Solution.* 与 Solution2.*是读者验证实现、对比语言差异的直接素材建议结合 README_EN.md 逐一对照阅读。赞分享示例工程教程【免费下载链接】leetcodeLeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer第 2 版》、《程序员面试金典第 6 版》题解项目地址https://gitcode.com/doocs/leetcode点击查看免费下载相关推荐doocs/leetcode 题解面试题 01.02 判定是否互为字符重排Check Permutation的计数与排序双解法doocs/leetcode 题解面试题 01.02 判定是否互为字符重排Check Permutation的计数与排序双解法 本文围绕 LeetCode示例工程教程scikit-learn 生态全景解读官方 Related Projects 目录与姊妹项目、扩展及领域工具scikit learn 生态全景解读官方 Related Projects 目录与姊妹项目、扩展及领域工具 导读 scikit learn 的官方文档中维护示例工程教程doocs/leetcode 面试题 01.01 判定字符是否唯一位运算掩码实现 O(1) 空间判重doocs/leetcode 面试题 01.01 判定字符是否唯一位运算掩码实现 O 1 空间判重 导读 本文围绕 doocs/leetcode 仓库中《程序示例工程教程上一篇Omi 组件属性 Props 完全指南JSX 传参、类型声明与跨框架原生使用下一篇PT 助手 Plus 种子文件校验如何确保下载完整性的终极验证机制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑