|
| 1 | +# Letter Tile Possibilities |
| 2 | + |
| 3 | +You are given a string, tiles, consisting of uppercase English letters. You can arrange the tiles into sequences of any |
| 4 | +length (from 1 to the length of tiles), and each sequence must include at most one tile, tiles[i], from tiles. |
| 5 | + |
| 6 | +Your task is to return the number of possible non-empty unique sequences you can make using the letters represented on |
| 7 | +tiles[i]. |
| 8 | + |
| 9 | +## Constraints: |
| 10 | + |
| 11 | +- 1 ≤ `tiles.length` ≤ 7 |
| 12 | +- The `tiles` string consists of uppercase English letters. |
| 13 | + |
| 14 | +## Examples |
| 15 | + |
| 16 | +Example 1: |
| 17 | + |
| 18 | +```text |
| 19 | +Input: tiles = "AAB" |
| 20 | +Output: 8 |
| 21 | +Explanation: The possible sequences are "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA". |
| 22 | +``` |
| 23 | + |
| 24 | +Example 2: |
| 25 | +```text |
| 26 | +Input: tiles = "AAABBC" |
| 27 | +Output: 188 |
| 28 | +``` |
| 29 | + |
| 30 | +Example 3: |
| 31 | +```text |
| 32 | +Input: tiles = "V" |
| 33 | +Output: 1 |
| 34 | +``` |
| 35 | + |
| 36 | +## Topics |
| 37 | + |
| 38 | +- Hash Table |
| 39 | +- String |
| 40 | +- Backtracking |
| 41 | +- Counting |
| 42 | + |
| 43 | +## Solutions |
| 44 | + |
| 45 | +### Permutations and Combinations |
| 46 | + |
| 47 | +This problem would have been straightforward if the tiles had no duplicates and we only needed to find sequences of the |
| 48 | +same length as the given tiles. In that case, we could simply calculate the total unique sequences using n! (where n is |
| 49 | +the length of the tiles). |
| 50 | + |
| 51 | + |
| 52 | + |
| 53 | +However, in this problem, we need to find all unique sequences of any length—from 1 to the full length of the tiles—while |
| 54 | +accounting for duplicate tiles. To achieve this, we take the following approach: |
| 55 | + |
| 56 | +We begin by sorting the letters in tiles so that similar letters are grouped. This allows us to systematically explore |
| 57 | +possible letter sets without repeating unnecessary work. |
| 58 | + |
| 59 | +To generate sequences of lengths ranging from 1 to n, we consider each letter one by one. We start with a single |
| 60 | +character, determine its possible sequences, then move to two-character combinations, find their possible sequences, |
| 61 | +and so on. For each new character, we have two choices: either include the current letter in our selection or skip it |
| 62 | +and move to the next one. By exploring both choices, we generate all possible letter sets. |
| 63 | + |
| 64 | +To prevent counting the same sequences multiple times due to duplicate letters, we ensure (in the previous step) that |
| 65 | +duplicate letter sets are not counted more than once while generating different letter sets. Then, for each set, we |
| 66 | +calculate how many distinct sequences can be formed by applying the updated formula for permutations, which accounts |
| 67 | +for repeated letters: `n! / c!`, where c is the count of each repeated letter. |
| 68 | + |
| 69 | +The more repeated letters in a set, the fewer unique ways it can be arranged. |
| 70 | + |
| 71 | +We repeat this process for every possible letter set. Eventually, we sum the count of all these possible sequences to |
| 72 | +obtain the total number of unique non-empty sequences. Finally, we subtract one from our final count to exclude the |
| 73 | +empty set, as it does not contribute to valid arrangements. |
| 74 | + |
| 75 | +Let’s look at the following illustration to understand this better. |
| 76 | + |
| 77 | + |
| 78 | + |
| 79 | +Now, let’s look at the algorithm steps of this solution: |
| 80 | + |
| 81 | +- Initialize a set, unique_letter_sets, to track unique letter sets. |
| 82 | +- Sort the input string, tiles, to group identical letters together. |
| 83 | +- Generate unique letter sets and count their permutations: |
| 84 | + - The function generate_sequences is used to recursively generate all possible letter subsets. |
| 85 | + - We calculate the number of valid sequences using `count_permutations` for each unique letter set. The |
| 86 | + `count_permutations` uses the helper function `factorial(n)`, which computes the factorial of a given number. |
| 87 | +- The recursive function, `generate_sequences(tiles, current_letter_set, index, unique_letter_sets)`, works as follows: |
| 88 | + - **Base case**: If `index` reaches the end of tiles, check if `current_letter_set` is unique. If it is: |
| 89 | + - Add it to `unique_letter_sets`. |
| 90 | + - Compute its permutations and return the count. |
| 91 | + - **Recursive cases**: |
| 92 | + - Exclude the current character (move to the next index). Store its result in the variable `without_letter`. |
| 93 | + - Include the current character (append it and move to the next index). Store its result in the variable `with_letter`. |
| 94 | + - The sum of both recursive calls gives the total count of valid sequences. |
| 95 | + - Once all the letters in tiles have been explored, return the output. As an empty set is also considered in the |
| 96 | + recursive process, we subtract 1 before returning the output. |
| 97 | + |
| 98 | + |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | + |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | + |
| 108 | + |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | + |
| 120 | +#### Time Complexity |
| 121 | + |
| 122 | +Let’s break down and analyze the time complexity of this solution: |
| 123 | +- Sorting the input string takes `O(n log(n))` time, where n is the length of the tiles. |
| 124 | +- The recursive function explores all possible subsets of the given tiles. As each tile can either be included or |
| 125 | + skipped, there are 2^n subsets in the worst case. |
| 126 | +- For each subset, we calculate the number of unique sequences that can be formed using the formula that accounts for |
| 127 | + duplicate letters. |
| 128 | + - Computing the factorial and handling character frequencies takes at most `O(n)` time per subset. |
| 129 | + - As we do this for all 2^n subsets, the total time complexity is `O(2 ^n × n)`, which dominates the sorting step. |
| 130 | + |
| 131 | +If we sum these up, the overall time complexity simplifies to: |
| 132 | + |
| 133 | +`O(nlogn) + O(2^n) + O(2^n×n) = O(2^n×n)` |
| 134 | + |
| 135 | +#### Space Complexity |
| 136 | +Let’s analyze the space complexity of this solution: |
| 137 | +- As the recursion goes as deep as the length of the string n, the worst case space used by the function calls is `O(n)`. |
| 138 | +- We store all unique subsets of tiles in a set, which can hold up to O(2^n) subsets in the worst case. Each sequence in |
| 139 | + the set can be up to length n. So, the set uses `O(2^n × n)` space. |
| 140 | +- The permutation calculation uses extra space, but this is at most O(n). |
| 141 | + |
| 142 | +If we add these up, the overall space complexity simplifies to: |
| 143 | + |
| 144 | +`O(n) + O(2^n × n) + O(n) = O(2^n × n)` |
0 commit comments