寶寶也能看懂的 leetcode 周賽 - 175 - 2

1347. 製造字母異位詞的最小步驟數

Hi 你們好,我是張小豬。歡迎來到『寶寶也能看懂』系列之 leetcode 周賽題解。git

這裏是第 175 期的第 2 題,也是題目列表中的第 1347 題 -- 『製造字母異位詞的最小步驟數』github

題目描述

給你兩個長度相等的字符串 st。每個步驟中,你能夠選擇將 t 中的 任一字符 替換爲 另外一個字符shell

返回使 t 成爲 s 的字母異位詞的最小步驟數。segmentfault

字母異位詞 指字母相同,但排列不一樣的字符串。優化

示例 1:spa

輸出:s = "bab", t = "aba"
輸出:1
提示:用 'b' 替換 t 中的第一個 'a',t = "bba" 是 s 的一個字母異位詞。

示例 2:code

輸出:s = "leetcode", t = "practice"
輸出:5
提示:用合適的字符替換 t 中的 'p', 'r', 'a', 'i' 和 'c',使 t 變成 s 的字母異位詞。

示例 3:blog

輸出:s = "anagram", t = "mangaar"
輸出:0
提示:"anagram" 和 "mangaar" 自己就是一組字母異位詞。

示例 4:leetcode

輸出:s = "xxyyzz", t = "xxyyzz"
輸出:0

示例 5:字符串

輸出:s = "friend", t = "family"
輸出:4

提示:

  • 1 <= s.length <= 50000
  • s.length == t.length
  • st 只包含小寫英文字母

官方難度

MEDIUM

解決思路

題目的意思仍是很直白的,其中最關鍵的一個信息就是,須要讓 t 成爲 s 的字母異位詞。那麼什麼是字母異位詞呢?即兩個字符串包含的字母的種類和數量都同樣。至於字母之間的排列順序,這裏上面官方的中文題目描述實際上是有問題的,由於英文原文是 "with a different (or the same) ordering.",因此字母順序實際上是能夠不一樣,也能夠相同的。

既然沒有了順序的顧慮,那麼咱們面臨的問題就只剩一個啦 -- 保證兩個字符串中字母的種類和數量都同樣。那麼說到這裏,咱們第一件要作的事情其實已經很是明顯了,就是對字符串進行字母頻率統計。如何統計呢?相信看過周賽第一題的小夥伴能夠輕鬆的想到,經過遍歷字符串並結合字典計數,即可完成對於字符串中出現字母的種類和數量進行統計。

假設如今咱們已經有了兩個字符串的字母統計結果,咱們應該如何找到最小的替換步數呢?這裏咱們能夠想象一下,對比這兩個字符串的字母統計結果,其實只可能會出現兩種狀況:

  • t 中某個字母的數量比 s 中多。
  • t 中某個字母的數量比 s 中少。

因爲咱們每一次替換字母是無任何要求的,因此咱們能夠將任何一個 ts 多的字母替換爲一個 ts 少的字母。而且,因爲 ts 這兩個字符串的長度必定相等,因此咱們這裏多出的數量和少的數量必定是相等的。也就是說,咱們最終要找的最少的替換步數,其實就是這個多出的數量或者少的數量。

直接方案

基於上面分析的思路,咱們能夠獲得以下的流程:

  1. 遍歷兩個字符串,獲得各自的字母統計結果。
  2. 對比兩個統計結果,獲得 t 字符串中比 s 多的數量。

基於這個流程,咱們能夠實現相似下面的代碼:

const minSteps = (s, t) => {
  const BASE = 97;
  const count1 = new Int32Array(26);
  const count2 = new Int32Array(26);
  for (let i = 0; i < s.length; ++i) {
    ++count1[s.charCodeAt(i) - BASE];
  }
  for (let i = 0; i < t.length; ++i) {
    ++count2[t.charCodeAt(i) - BASE];
  }
  let step = 0;
  for (let i = 0; i < 26; ++i) {
    step += count1[i] > count2[i] ? count1[i] - count2[i] : 0;
  }
  return step;
};

優化

上面的代碼裏,咱們統計了兩次計數結果,而且也遍歷了兩次字符串長度。那麼咱們是否能夠削減一半呢?

這時咱們注意一下最終咱們須要的是什麼,會發現其實咱們要的只是二者的差值,而它們的數量到底是多少其實咱們是不關心的。基於這個想法,咱們能夠嘗試直接在一次遍歷中計算差值,而不是統計總數量。

基於上面分析的思路,咱們能夠獲得以下的流程:

  1. 遍歷一次字符串的長度。
  2. 對於兩個字符串中出現的字母,計算對應字母的統計差值。
  3. 對差值中的正數求和並返回。

基於這個流程,咱們能夠實現相似下面的代碼:

const minSteps = (s, t) => {
  const BASE = 97;
  const count = new Int32Array(26);
  for (let i = 0; i < s.length; ++i) {
    ++count[s.charCodeAt(i) - BASE];
    --count[t.charCodeAt(i) - BASE];
  }
  let step = 0;
  for (let i = 0; i < 26; ++i) {
    count[i] > 0 && (step += count[i]);
  }
  return step;
};

總結

這道題內容很是直白,而核心的點就在於最終需求的要求。一旦咱們分析明白了這個需求,咱們也就能夠很容易的基於此獲得實現方案。

其實熟悉了的話,徹底能夠直接寫出上面優化版本的代碼,小豬在比賽中也是直接提交的這個代碼。不過爲了展現這個優化的思路,小豬在這裏仍是先給出了直接方案的代碼。小豬是否是很貼心鴨,嘿嘿嘿~ 快誇誇小豬,嚶嚶嚶 >.<

相關連接

qrcode_green.jpeg

相關文章
相關標籤/搜索