题目描述
思路解析动画文字版
数 e 扫一遍、数 l 再扫一遍……每种字符都重扫全串,重复劳动太多。我们想要的是只扫一遍就把所有次数全数清。
哈希表像一本点名册:字符是名字,值是「来了几次」。只走一遍,所有次数就全在册子上,这步只要 O(n)。下面用柱子把这一遍数清楚的过程演给你看。
第一步 · 数次数(扫描前):"loveleetcode" 里有 7 种不同字符 l o v e t c d。这 7 根柱子是它们的计数,现在都是 0。我们从左到右扫一遍,每见一个字符就把对应柱子升高 1。
扫到 'l' · l 计数 +1:第 1 个字符是 l,点名册给 l 记一笔,l 的柱子升到 1。
扫到 'o' · o 计数 +1:第 2 个是 o,第一次见,o 的柱子升到 1。
扫到 'v' · v 计数 +1:第 3 个是 v,v 的柱子升到 1。
扫到 'e' · e 计数 +1:第 4 个是 e,第一次见 e,e 的柱子升到 1。
扫到 'l' · l 计数 +1:第 5 个又是 l,再给 l 记一笔,l 升到 2。重复的字符不新开格子,只是把已有计数 +1。
扫到 'e' · e 计数 +1:第 6 个又是 e,e 升到 2。e 开始追上来了。
扫到 'e' · e 计数 +1:第 7 个还是 e,e 升到 3,已经是最高的柱子了。
扫到 't' · t 计数 +1:第 8 个是 t,第一次见,t 的柱子升到 1。
扫到 'c' · c 计数 +1:第 9 个是 c,第一次见,c 的柱子升到 1。
扫到 'o' · o 计数 +1:第 10 个又是 o,o 升到 2,和 l 并列第二。
扫到 'd' · d 计数 +1:第 11 个是 d,第一次见,d 的柱子升到 1。
扫到 'e' · e 计数 +1(扫描结束):最后第 12 个又是 e,e 升到 4!整串扫完,次数全清楚:e=4, l=2, o=2, v=1, t=1, c=1, d=1。只扫了一遍(O(n))。
点名册(哈希表)记完:哈希表里每个字符对应它的计数。只扫一遍就全数清,比反复数快得多。接下来就是按计数把字符排好队。
要排的不是 12 个字符,而是 7 种不同字符,按它们的计数降序。种类少,排序很快。也可以用大顶堆每次取最多的,本质一样。
按计数从高到低排好:排序后柱子顺序变了:e(4) 排最前,l、o(各 2)次之,v、t、c、d(各 1)垫底。现在柱子从左到右的顺序,就是输出里字符块的顺序。
拼结果 · 取计数最高的 e:从计数最高的 e 开始取:e 出现 4 次,就把 4 个 e 一起拼上去。当前结果:eeee。
拼结果 · 再取 l:下一个是 l,出现 2 次,拼 2 个 l。当前结果:eeeell。
拼结果 · 再取 o:再取 o,也出现 2 次,拼 2 个 o。当前结果:eeeelloo。
拼结果 · 取 v:接下来都是 1 次的字符。先取 v,拼 1 个 v。当前结果:eeeelloov。
拼结果 · 取 t:取 t,拼 1 个 t。当前结果:eeeelloovt。
拼结果 · 取 c:取 c,拼 1 个 c。当前结果:eeeelloovtc。只剩最后一个 d 了。
拼结果 · 取 d(完成):最后取 d,拼 1 个 d。所有字符放完,结果 = eeeelloovtcd,长度 12,和原串一样长,正是题目要的答案。
雷区实演 · 忘了重复字符:如果拼接时每个字符只放一个,e 明明出现 4 次却只放 1 个,得到 elovtcd(长度才 7,原串是 12)——长度都不对。一定要 字符 × 计数。
边界三连:先想最小(单字符)、最极端(全相同)、最平均(全不同)三种。注意同次数时顺序任意,评测会接受多种答案。
面试追问:把「哈希计数 + 按计数排序」这套组合讲清楚,是这题的得分点,它能套到一大类高频统计题。
参考代码
from collections import Counterclass Solution: def frequencySort(self, s): cnt = Counter(s) # 扫一遍数次数 # 按计数从大到小排序字符 chars = sorted(cnt, key=lambda c: cnt[c], reverse=True) res = [] for c in chars: res.append(c * cnt[c]) # 字符 × 它的次数 return "".join(res)复杂度
- 时间复杂度:O(n + k log k),数次数扫一遍 O(n);对 k 种不同字符排序 O(k log k)。k 是字符种类数(ASCII 最多 128),很小
- 空间复杂度:O(n),哈希表存 k 种字符的计数 O(k);结果字符串长度等于原串 O(n)
易错点
面试追问把动画讲成自己的话
追问为什么用哈希表数次数而不是反复扫?
追问排序解法和堆解法有什么区别?
追问如果字符只可能是小写字母,能更快吗?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。再去主线里挑下一道练手。
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题