Skip to content

LeetCode: 1079. Letter Tile Possibilities 解題紀錄

Last Updated on 2025-02-17 by Clay

題目

You have n  tiles, where each tile has one letter tiles[i] printed on it.

Return the number of possible non-empty sequences of letters you can make using the letters printed on those tiles.

Example 1:

Input: tiles = "AAB"
Output: 8
Explanation: The possible sequences are "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA".

Example 2:

Input: tiles = "AAABBC"
Output: 188

Example 3:

Input: tiles = "V"
Output: 1

Constraints:

tiles consists of uppercase English letters.

1 <= tiles.length <= 7

題目本質上是不重複的所有排列組合數量,並允許只取 1 ... tiles.length 的長度。


解題思路

一開始我總想著套用數學公式來解題,但我想來想去還是推不出公式... (汗顏)最後還是回歸到了工程師擅長的暴力破解 —— 遞迴遍歷全部組合。

我認為重點在於其實是把 AAABB 這樣的輸入,理解為 {"A": 3, "B": 2} 這樣的字典,然後我們在每個時間點,只能從字典中選擇一個字母(letter)出來組成當下的排列,並且把排列的計數 + 1、字典中可選的字母數量 - 1。

計算完之後,我們需要把當前殘存的字典狀態繼續往下走遞迴,一直到字典中沒有可選的字母時才停止計數;與此同時,也要記得在遞迴結束後把字典的狀態還原回來(也就是把當下字母數量 - 1 的部份,在走完遞迴後 + 1 回來),畢竟在我們取下一個字典的字母時,前一個取的字母還是完整的。

簡單來說,假設我們現在當前狀態取了 A ,我們的字典應該變成了 {"A": 2, "B": 2},但是當我們準備在當前狀態取 B 時,我們需要先把字典還原回初始狀態 {"A": 3, "B": 2},不然就會在取 B 後,突然發現字典的 AB 雙雙減少了,變成 {"A": 2, "B": 1}


複雜度

Time Complexity = O(n!) (假設沒有重複的情況,時間複雜度應應在 n!,實際上因為字母會重複,複雜度應該更小一點)

Space Complexity = O(n)


C++ 範例程式碼

class Solution {
public:
    void DFS(unordered_map<char, int>& char2times, int& count) {
        for (const auto& [c, times] : char2times) {
            if (times == 0) {
                continue;
            }

            // Recursive
            --char2times[c];
            ++count;
            DFS(char2times, count);

            // Recovery
            ++char2times[c];
        }
    }

    int numTilePossibilities(string tiles) {
        // Init
        int count = 0;
        std::unordered_map<char, int> char2times;
        for (char& c: tiles) {
            ++char2times[c];
        }

        DFS(char2times, count);

        return count;
    }
};



Python 範例程式碼

class Solution:
    def DFS(self) -> None:
        for tile, times in self.tile2times.items():
            if times == 0:
                continue

            self.tile2times[tile] -= 1
            self.count += 1
            self.DFS()

            self.tile2times[tile] += 1


    def numTilePossibilities(self, tiles: str) -> int:
        # Init
        self.count = 0
        self.tile2times = {}
        for tile in tiles:
            self.tile2times[tile] = self.tile2times.get(tile, 0) + 1
        
        # DFS
        self.DFS()

        return self.count

References


Read More

Leave a Reply取消回覆

Exit mobile version