寶寶也能看懂的 leetcode 周賽 - 170 - 1

1309. 解碼字母到整數映射

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

這裏是第 170 期的第 1 題,也是題目列表中的第 1309 題 -- 『解碼字母到整數映射』github

題目描述

給你一個字符串 s,它由數字('0' - '9')和 '#' 組成。咱們但願按下述規則將 s 映射爲一些小寫英文字符:正則表達式

  • 字符('a' - 'i')分別用('1' - '9')表示。
  • 字符('j' - 'z')分別用('10#' - '26#')表示。

返回映射以後造成的新字符串。shell

題目數據保證映射始終惟一。segmentfault

示例 1:數據結構

輸入:s = "10#11#12"
輸出:"jkab"
解釋:"j" -> "10#" , "k" -> "11#" , "a" -> "1" , "b" -> "2".

示例 2:編輯器

輸入:s = "1326#"
輸出:"acz"

示例 3:spa

輸入:s = "25#"
輸出:"y"

示例 4:code

輸入:s = "12345678910#11#12#13#14#15#16#17#18#19#20#21#22#23#24#25#26#"
輸出:"abcdefghijklmnopqrstuvwxyz"

提示:blog

  • 1 <= s.length <= 1000
  • s[i] 只包含數字('0'-'9')和 '#' 字符。
  • s 是映射始終存在的有效字符串。

官方難度

EASY

解決思路

這道題很是直白,是處理一個從數字到字符串的映射關係。其中映射區間分爲兩段,[1, 9][10, 26],然後者會用一個後置的 '#' 符號進行標識區分。

讀完題目,個人第一反應是,那咱們先搞個字典用於記錄和查詢映射關係吧。省得每次使用或者轉換的時候都須要去計算。

在喊出魔法咒語『巴拉巴拉 張小豬是最美(pang)的』以後,個人編輯器裏就出現了下面這個字典。

const map = {"1":"a","2":"b","3":"c","4":"d","5":"e","6":"f","7":"g","8":"h","9":"i","10":"j","11":"k","12":"l","13":"m","14":"n","15":"o","16":"p","17":"q","18":"r","19":"s","20":"t","21":"u","22":"v","23":"w","24":"x","25":"y","26":"z"};

你們也能夠試一試啦。要是萬一不行的話,經過一個循環結合 JSON.stringify 應該能夠很容易生成這個字符串。我這裏就不貼相關的代碼啦,纔不是由於我忘記保留而且又懶得再敲一遍了呢(確信臉)

有了上面這個字典以後,咱們該如何進行字符串的遍歷和轉換呢?下面提供三種不一樣的思路,方便小夥伴們發散思惟和取捨。也歡迎小夥伴們分享更多有意思的思路,小豬在此先行阿里嘎多。

基於 stack 實現

這種實現思路是,基於 stack 這種數據結構的特色,即 FILO(先進後出),來處理後置 '#' 這個特殊字符,從而區分兩個不一樣的映射區間,最終實現咱們的目標。具體流程以下:

  1. 從頭開始遍歷原始字符串。
  2. 對全部遇到的數字進行入棧操做。

    • 若是遇到了數字,則進行入棧操做。
    • 若是遇到了 '#' 這個特殊字符,進行兩次出棧操做,並將獲得的內容拼接後進行 [10, 26] 區間的映射轉換,將映射結果從新入棧。
  3. 當遍歷完原始字符串後,對當前棧不斷的執行出棧操做。

    • 若是遇到數字進行 [1, 9] 區間的映射轉換,而後進行拼接
    • 若是數字則直接進行拼接。
  4. 返回最終拼接好的結果。

基於該流程能夠寫出相似以下的代碼:

const freqAlphabets = s => {
  const stack = [];
  for (const char of s) {
    if (char !== '#') { stack.push(char); continue; }
    const digit = stack.pop();
    stack.push(map[(stack.pop() + digit)]);
  }
  let ret = '';
  for (const char of stack) {
    ret += char <= '9' ? map[char] : char;
  }
  return ret;
};

這裏順便說一下,這種思路實際上是一種處理字符串遍歷中後置特殊判斷的相對通用思路。相信小夥們在刷題過程當中應該還能再遇到能夠基於這個思路解決的問題。Fighting!

基於本題的邏輯直接遍歷實現

針對本題具體的邏輯,其實能夠進行更簡單的直接實現。具體流程以下:

  1. 從頭開始遍歷原始字符串。
  2. 檢測 i + 2 這個下標是否爲特殊字符 '#'。

    • 若是不是則進行 [0, 9] 區間的映射轉換,而後進行拼接。
    • 若是是則對 ii + 1 進行 [10, 26] 區間的映射轉換,而後進行拼接,注意跳過 i + 2
  3. 返回最終拼接好的字符串。

基於該流程能夠寫出相似以下的代碼:

const freqAlphabets = s => {
  let ret = '';
  for (let i = 0; i < s.length; ++i) {
    ret += map[s[i + 2] === '#' ? (i += 2, s[i - 2] + s[i - 1]) : s[i]];
  }
  return ret;
};

基於正則表達式實現

這個思路就很是簡單啦,基於正則表達式作一個匹配、轉換和替換便可。因爲 JS 中字符串的 replace 方法支持正則,因而能夠直接實現相似以下的代碼:

const freqAlphabets = s => s.replace(/(\d\d#|\d)/g, t => map[t.length === 3 ? t[0] + t[1] : t]);

總結

周賽第一題,慣例的保底送分題。因此就嘗試從不一樣的思路給予一些方案。
不過這篇文章的核心點是引入『巴拉巴拉 張小豬是最美(pang)的』這句魔法咒語,以便後續使用 >.<

相關連接

qrcode_green.jpeg

相關文章
相關標籤/搜索