優化演算法練習 Leetcode X Valid Anagram
今天來探討 Anagram 字謎的 Easy 演算法練習題目,認識新的 Count Array 計算陣列統計法。
拆解題目
242. Valid Anagram
Given two strings s and t, return true if t is an anagram of s, and false otherwise.
Example 1:
Input: s = “anagram”, t = “nagaram”
Output:true
Example 2:
Input: s = “rat”, t = “car”
Output:false
Constraints:
1 <= s.length, t.length <= 5 * 104s and t consist of lowercase English letters.
解答思考
sort 暴力字母排序法
題目需要將相同小寫英文字母的組成視為 true 排序則不管:例如 car 和 acr、rca、arc 等等就返回 true。
我腦海想到的第一個做法就是暴力解 sort 將 s 和 t 字串按照字母順序排列後相同就表示組成一樣!
但我自己很清楚這個時間的演算效率會是 *log(n log n)*,一定有更好的解法。
1 | /** |
寫起來很簡潔但運算效率要仰賴 a、b 字元的前後比對交換,花費的時間多效率差。
所以今天來多學兩個更好的作法。
Count Array 計數陣列演算法
計數陣列的作法可以理解為 **計數白板(Counting whiteboard)**,把 26 個字母從 a - z 以 ASCII (American Standard Code for Information Interchange,美國標準資訊交換碼) 十進位制的特色來破解題目。
我們來借用一下實作原理需要的 Method charCodeAt 來反推小寫英文的 UTF-18 編碼十進位制:
從上圖可以知道小寫字母的 ASCII 十進位制代碼從 a 的數字 97 到 z 的 122,都是按照規則 i++ 的順序排列的,我們可以借用此規則當作陣列的索引值:
1 | 'a'.charCodeAt(0) // 26 |
使用一個固定長度 Array(26) 並且每個所以從 0 計算該字母在 s 字串中出現幾次、並於 t 字串中一一扣除,如若最後該陣列計分板都歸 0 就表示兩個陣列無論在字母還是數量上都相等:
1 | /** |
將每個字母出現在 s 的索引值 value ++; 將每個字母出現在 t 的索引值 value –; 這樣的用意在統計某個英文字母是否在兩個字串出現的頻率相同:例如 a 出現在 s 字串中 n 次、在另一個 t 字串也一定會出現 n 次,用這樣的邏輯來消除每一個字母,若出現負數或正數就表示兩個字串不符合此**字謎(Anagram)**邏輯。
Hashmap 雜湊地圖演算法
是演算法裡的老朋友了,把 s 字串當作字典,並且將出現的次數一一紀錄後,由 t 字串來查詢是否符合字典裡的要求:字母、次數。
1 | /** |
提高效率的小撇步:將 for(let item of arr) 以 for(let i; i < ...) 來取代可以減少背後呼叫 arrSymbol.iterator物件去逐個取得元素,根據裝置 / 瀏覽器略有不同,但通常 for 會快 1.5~2 倍以上。
1 | /** |
取決於公司偏重大量資料下取求速還是易維護,各有所好沒有對錯~~
以上就是這次的解題分享,感謝 ChatGpt 老師 =)