手摸手提桶跑路——LeetCode2186. 使两字符串互为字母异位词的最少步骤数

250 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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

  • st 由小写英文字符组成

解题思路

如果我们想将 leetcodecode 变为异位字符串,那么我们必须对字符串2连续追加 L、e、e、t 四个字母。

如果我们想将 hellocatwatermelonhicat 变为异位字符串,那么由于字符串1缺少字母i,因此它至少要追加一次 i 字母,才可以全包含 hicat 字符串,而 hicat 需要追加 ellowatermelon 两串共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中,就是键为两个字符串中所有字母,值就是出现的次数。

别忘了统计结果需要进行绝对值操作。

结束语

面对”看不懂“的题目时,我们需要静下心来,将问题简化成另一个问题,更有利于提高我们跑路的效率,在自己写出题解时,也要多看看别人的解法,取其精华,拿来吧你。