Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Letter Tile Possibilities in Python
Given a set of letter tiles, we need to find the number of possible non-empty sequences we can make using these tiles. For example, with tiles "AAB", we can form 8 different sequences: "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA".
This problem uses backtracking with frequency counting to generate all possible permutations while avoiding duplicates.
Algorithm Approach
We use a depth-first search (DFS) approach with the following steps:
- Count the frequency of each letter in the input tiles
- For each recursive call, try using each available letter
- Backtrack by restoring the letter count after exploration
- Sum all possible sequences at each level
Implementation
Here's the complete solution using backtracking ?
class Solution:
def numTilePossibilities(self, tiles):
# Count frequency of each letter (A-Z)
count = [0] * 26
for tile in tiles:
count[ord(tile) - ord('A')] += 1
return self.dfs(count)
def dfs(self, count):
total = 0
# Try each letter from A to Z
for i in range(26):
if count[i] == 0:
continue
# Use this letter
count[i] -= 1
total += 1 # Count this single letter sequence
total += self.dfs(count) # Count sequences starting with this letter
count[i] += 1 # Backtrack
return total
# Test the solution
solution = Solution()
print(solution.numTilePossibilities("AAB"))
print(solution.numTilePossibilities("AAABBC"))
The output of the above code is ?
8 188
How It Works
The algorithm works by:
- Frequency counting: We count how many times each letter appears
- DFS exploration: At each level, we try placing each available letter
- Backtracking: After exploring with a letter, we restore its count
- Counting sequences: Each time we use a letter, we count it as one valid sequence
Step-by-Step Example
For tiles "AAB", the frequency count is [2, 1, 0, ...] (A appears 2 times, B appears 1 time):
def trace_solution(tiles):
solution = Solution()
# Show frequency counting
count = [0] * 26
for tile in tiles:
count[ord(tile) - ord('A')] += 1
print(f"Input tiles: {tiles}")
print(f"Frequency - A: {count[0]}, B: {count[1]}")
print(f"Total possibilities: {solution.numTilePossibilities(tiles)}")
trace_solution("AAB")
Input tiles: AAB Frequency - A: 2, B: 1 Total possibilities: 8
Time and Space Complexity
The time complexity is O(N!) where N is the number of tiles, as we explore all possible permutations. The space complexity is O(N) for the recursion stack and frequency array.
Conclusion
This backtracking approach efficiently counts all possible letter sequences by using frequency counting to avoid duplicate calculations. The DFS method explores every valid combination while maintaining optimal performance through pruning.
