携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情
题目描述
给你两个字符串 s 和 t 。在一步操作中,你可以给 s 或者 t 追加 任一字符 。
返回使 s 和 t 互为 字母异位词 所需的最少步骤数。
字母异位词 指字母相同但是顺序不同(或者相同)的字符串。
示例 1:
输入:s = "leetcode", t = "coats"
输出:7
解释:
- 执行 2 步操作,将 "as" 追加到 s = "leetcode" 中,得到 s = "leetcodeas" 。
- 执行 5 步操作,将 "leede" 追加到 t = "coats" 中,得到 t = "coatsleede" 。
"leetcodeas" 和 "coatsleede" 互为字母异位词。
总共用去 2 + 5 = 7 步。
可以证明,无法用少于 7 步操作使这两个字符串互为字母异位词。
示例 2:
输入:s = "night", t = "thing"
输出:0
解释:给出的字符串已经互为字母异位词。因此,不需要任何进一步操作。
提示:
-
1 <= s.length, t.length <= 2 * 105 -
s和t由小写英文字符组成
解题思路
如果我们想将 leetcode 和 code 变为异位字符串,那么我们必须对字符串2连续追加 L、e、e、t 四个字母。
如果我们想将 hellocatwatermelon 和 hicat 变为异位字符串,那么由于字符串1缺少字母i,因此它至少要追加一次 i 字母,才可以全包含 hicat 字符串,而 hicat 需要追加 ello 及 watermelon 两串共12个字母,才能与字符串1匹配。
那我怎么知道给字符串加啥,给字符串2加啥,才能让它们变成异位?
通过分析可以知道,其中一个字符串至少要包含另一个字符串中的所有字符且个数相同,它们才可以成为 异位字符串。
那么我们的问题就从求最小异位步骤,变成了分别计算两个字符串中对应字母的数量的问题了。
leetcode 中:
{
l: 1,
e: 3,
t: 1,
c: 1,
o: 1,
d: 1
}
code中:
{
c: 1,
o: 1,
d: 1,
e: 1
}
可以看出字符串1中满足了组成字符串2的所有字母个数。
且部分多出来,那么这多出来的几个字母,就是字符串2中,想组成字符串1需要的剩余字母。
至此,我们可以得到:最小异位步骤=两个字符串中字母数量的差。
我们只需要计算第一个字符串的所有字母数量,然后用第二个字符串不断去减,最终单个字符统计的结果为正数的,则说明是字符串1中多余的(字符串2中缺失的),最终结果为负的,则说明是字符串2中多余的(字符串1中缺失的)。
题解
/**
* @param {string} s
* @param {string} t
* @return {number}
*/
var minSteps = function(s, t) {
const map = {};
for(let w of s) {
map[w]++ || (map[w] = 1);
};
for(let w of t) {
map[w]-- || (map[w] = -1);
};
return Object.values(map).reduce((f,c)=>f+Math.abs(c),0);
};
首先遍历第一个串。
将第一次遇见的置为1,再次遍历则进行+1操作。
然后遍历第二个串,首次遇见的我们标记为-1,为什么是-1呢?还记得上面提到的,如果为负数,表示的是字符串1中缺失的,所以这里的初始值应该是置-1的。
最后得到的map中,就是键为两个字符串中所有字母,值就是出现的次数。
别忘了统计结果需要进行绝对值操作。
结束语
面对”看不懂“的题目时,我们需要静下心来,将问题简化成另一个问题,更有利于提高我们跑路的效率,在自己写出题解时,也要多看看别人的解法,取其精华,拿来吧你。