LeetCode 1347中等哈希/字符串
制造字母异位词的最小步骤数 图解题解
这道题到底在问什么
给定等长小写串 s、t。每步把 t 中一个字符替换为任意字符,求让 t 成为 s 的字母异位词所需最少替换次数。
- 输入
- s="bab", t="aba"
- 输出
- 1
- 输入
- s="leetcode", t="practice"
- 输出
- 5
最优解:一步一步想明白
- 3记住「s 建需求账本 → 扫 t:账本还要就认领、不要就替换」,下面每帧都在套它。
- 4屏幕上是 t="practice" 的每个字符,待会儿一个个判断它该保留还是替换。
- 5先统计 s 的需求账本:c×1 d×1 e×3 l×1 o×1 t×1。这就是 t 最终要凑齐的字母清单。
- 6开始从左到右扫 t。指针指向当前字符,对照账本决定它的命运。
- 7扫到 t[0]=p。查账本:p 还需要 0 个。不需要了 → 多余。
- 8p 是多余的(红色),必须替换掉,已替换 1 步。
- 9扫到 t[1]=r。查账本:r 还需要 0 个。不需要了 → 多余。
- 10r 是多余的(红色),必须替换掉,已替换 2 步。
- 11扫到 t[2]=a。查账本:a 还需要 0 个。不需要了 → 多余。
- 12a 是多余的(红色),必须替换掉,已替换 3 步。
- 13扫到 t[3]=c。查账本:c 还需要 1 个。还需要 → 可以认领。
- 14c 被认领(绿色),s 账本里 c 减到 0。这个字符保留、不用改。
- 15扫到 t[4]=t。查账本:t 还需要 1 个。还需要 → 可以认领。
- 16t 被认领(绿色),s 账本里 t 减到 0。这个字符保留、不用改。
- 17扫到 t[5]=i。查账本:i 还需要 0 个。不需要了 → 多余。
- 18i 是多余的(红色),必须替换掉,已替换 4 步。
- 19扫到 t[6]=c。查账本:c 还需要 0 个。不需要了 → 多余。
- 20c 是多余的(红色),必须替换掉,已替换 5 步。
- 21扫到 t[7]=e。查账本:e 还需要 3 个。还需要 → 可以认领。
- 22e 被认领(绿色),s 账本里 e 减到 2。这个字符保留、不用改。
- 23扫完 t:绿色 3 个是能保留的,红色 5 个是多余、必须替换的。所以最少替换 5 步——把这 5 个红字符改成 s 还缺的字母即可。
⚠️ 容易写错的地方
✗ 错:把顺序也当成要求
✓ 对:异位词只看字母个数,顺序无所谓
aba 和 baa 互为异位词,不用管位置
✗ 错:正差负差都累加
✓ 对:只累加正差(s 多出的)
等长时正差和=负差和,取一边即可,重复加会翻倍
✗ 错:以为要同时改 s 和 t
✓ 对:只改 t,把 t 多余的替换成 s 缺的
每次替换同时消掉一个「多余」和补上一个「缺」
完整代码(Python / C++ / Java)
Python
class Solution:
def minSteps(self, s: str, t: str) -> int:
cnt = [0] * 26
for ch in s:
cnt[ord(ch) - 97] += 1
for ch in t:
cnt[ord(ch) - 97] -= 1
return sum(x for x in cnt if x > 0)C++
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
int minSteps(string s, string t) {
vector<int> cnt(26);
for (char c : s) cnt[c - 'a']++;
for (char c : t) cnt[c - 'a']--;
int ans = 0;
for (int x : cnt) if (x > 0) ans += x;
return ans;
}
};Java
import java.util.*;
class Solution {
public int minSteps(String s, String t) {
int[] cnt = new int[26];
for (char c : s.toCharArray()) cnt[c - 'a']++;
for (char c : t.toCharArray()) cnt[c - 'a']--;
int ans = 0;
for (int x : cnt) if (x > 0) ans += x;
return ans;
}
}复杂度
时间
O(n)
各扫 s、t 一遍
空间
O(1)
固定 26 个字母的计数
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 制造字母异位词的最小步骤数 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
为什么「t 多余字符数」就等于答案?+
每做一次替换,把 t 里一个多余字符改成 s 里还缺的字母,一步同时消掉「一个多余」和「一个缺口」。多余字符有几个,就要几步,所以答案 = t 中多余字符数 = sum 正差。
如果 s、t 不等长还能这么做吗?+
本题保证等长。若不等长,异位词不可能(字母总数都不同),或题意会变成「插入/删除」编辑距离类问题,需另解。等长是这个简单计数法成立的前提。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄声线把 制造字母异位词的最小步骤数 一步步讲透(全站 0 节语音精讲,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。