[LeetCode] 49. Group Anagrams

題目

Given an array of strings strs, group the anagrams together. You can return the answer in any order.
An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

  • 1 < = strs.length <= 104

  • 0 <= strs[i].length <= 100

  • strs[i] consists of lower-case English letters.

直覺解

構想:

result 的格式預計就是要回傳的答案。比對 strs 中每個字串,是否和 result 中任一元素的第一個元素,都使用一樣且數量相同的字母。比對的方式是,雙方同時刪掉某個特定字母,刪完之後雙方長度是否一樣。

javascript 實作:

const groupAnagrams = function(strs) { 
    if (strs.length < 2) { return [strs]}

    const result = []
    strs.forEach(str => {
        let isGrouped = false

        for (const group of result) {
            let isAnagram = true

            if (group[0].length !== str.length) {
                isAnagram = false
                continue
            }

            let originalLetters = group[0]
            let string = str
            for (let i = string.length - 1; i >= 0 ; i--) {
                if (originalLetters === string) {
                    break
                }

                originalLetters = originalLetters.replace(string[i], '')
                string = string.replace(string[i], '')

                if (originalLetters.length !== string.length) {
                    isAnagram = false
                    break
                }
            }
            if (isAnagram) {
                group.push(str)
                isGrouped = true
                break
            }
        }
        if (!isGrouped) {
            result.push([str])
        }
    })

    return result
}

效能:

Runtime: 2268 ms, faster than 5.00% of JavaScript online submissions for Group Anagrams.
Memory Usage: 48.6 MB, less than 88.76% of JavaScript online submissions for Group Anagrams.

犯過的錯誤:

  • 題目寫「typically using all the original letters exactly once」,所以以為這不是題目的限制之一,於是在 strs = ["ddddddddddg","dgggggggggg"] 時把這兩個字串分在同一組,結果就答錯了。
  • 因為我刪除比對過的字母的方式是,把比對過的字母用空字串取代,所以 strs 中有空字串時,沒辦法用「把比對過的字母用空字串取代」的方式處理。最後是當成例外狀況來處理,不過程式碼看起來就更不精簡了。
  • 「把比對過的字母用空字串取代」計算起來滿花時間的,在效能上很不理想。

參考別人的解後,javascript 實作優化:

構想:紀錄 26 個字母中,每個字母出現幾次,把這個紀錄當作分組的標籤。

const groupAnagrams = function(strs) { 
    if (strs.length < 2) { return [strs] }
    const result = []

    strs.forEach(str => {
        const codeOfa = 'a'.charCodeAt(0)
        const map = Array.from({ length: 26 }, item => 0)

        for (const index in str) {
            map[str.charCodeAt(index) - codeOfa]++
        }
        const groupTag = map.join('-')
        let isGroup = false

        for (const group of result) {
            if (group[0] === groupTag) {
                group.push(str)
                isGroup = true
                break
            }
        }

        if (!isGroup) {
            result.push([groupTag, str])
        }
    })

    for (const group of result) {
        group.splice(0, 1)
    }

    return result
}

效能:

Runtime: 976 ms, faster than 5.00% of JavaScript online submissions for Group Anagrams.
Memory Usage: 50.9 MB, less than 22.02% of JavaScript online submissions for Group Anagrams.

犯過的錯誤:

  • tag 沒有加分隔號,結果 strs = ["bdddddddddd","bbbbbbbbbbc"] 時,兩者的 tag 剛好一樣。

參考別人的解後,javascript 實作優化:

構想:group 從陣列改成物件,這樣要比對分組標籤時就不需迭代陣列。簡化取得分組標籤的方式。

const groupAnagrams = function(strs) { 
    if (strs.length < 2) { return [strs] }
    const group = {}

    strs.forEach(str => {
        const groupKey = str.split('').sort().join('')
        if (!group[groupKey]) {
            group[groupKey] = [str]
        } else {
            group[groupKey].push(str)
        }
    })

    return Object.values(group)
}

效能:

Runtime: 132 ms, faster than 67.62% of JavaScript online submissions for Group Anagrams.
Memory Usage: 49.8 MB, less than 50.17% of JavaScript online submissions for Group Anagrams.

Comments

Popular posts from this blog

shop_platform - 建立多對多關聯:Association Object

[計算機概論] SR Flip-Flop

git 指令