Skip to content

Commit 20e50ac

Browse files
Add explanation and solution for LeetCode problem 290 (Word Pattern)
1 parent ad2075f commit 20e50ac

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

explanations/290/en.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
## 290. Word Pattern [Easy]
2+
3+
https://leetcode.com/problems/word-pattern
4+
5+
## Description
6+
Given a `pattern` and a string `s`, find if `s` follows the same pattern.
7+
8+
Here **follow** means a full match, such that there is a bijection between a letter in `pattern` and a **non-empty** word in `s`. Specifically:
9+
10+
- Each letter in `pattern` maps to **exactly** one unique word in `s`.
11+
- Each unique word in `s` maps to **exactly** one letter in `pattern`.
12+
- No two letters map to the same word, and no two words map to the same letter.
13+
14+
**Examples**
15+
16+
```tex
17+
Example 1:
18+
Input: pattern = "abba", s = "dog cat cat dog"
19+
Output: true
20+
Explanation:
21+
The bijection can be established as:
22+
- 'a' maps to "dog".
23+
- 'b' maps to "cat".
24+
25+
Example 2:
26+
Input: pattern = "abba", s = "dog cat cat fish"
27+
Output: false
28+
29+
Example 3:
30+
Input: pattern = "aaaa", s = "dog cat cat dog"
31+
Output: false
32+
```
33+
34+
**Constraints**
35+
```tex
36+
- 1 <= pattern.length <= 300
37+
- pattern contains only lower-case English letters
38+
- 1 <= s.length <= 3000
39+
- s contains only lowercase English letters and spaces ' '
40+
- s does not contain any leading or trailing spaces
41+
- All the words in s are separated by a single space
42+
```
43+
44+
## Explanation
45+
46+
### Strategy
47+
Let's restate the problem: You're given a pattern string (like "abba") and a string of words (like "dog cat cat dog"), and you need to determine if the words follow the same pattern. This means there should be a one-to-one mapping between letters in the pattern and words in the string.
48+
49+
This is a **hash table problem** that requires tracking bidirectional mappings between pattern characters and words, similar to the isomorphic strings problem but with words instead of individual characters.
50+
51+
**What is given?** A pattern string and a string of space-separated words.
52+
53+
**What is being asked?** Determine if the words follow the same pattern as the given pattern string.
54+
55+
**Constraints:** The pattern can be up to 300 characters, and the string can be up to 3000 characters with words separated by single spaces.
56+
57+
**Edge cases:**
58+
- Pattern and words have different lengths
59+
- Empty pattern or empty string
60+
- Pattern with repeated characters
61+
- String with repeated words
62+
63+
**High-level approach:**
64+
The solution involves using two hash maps to track character-to-word and word-to-character mappings, ensuring that the bijection property is maintained.
65+
66+
**Decomposition:**
67+
1. **Split the string into words**: Convert the space-separated string into a list of words
68+
2. **Check length consistency**: If pattern length doesn't match word count, return false
69+
3. **Create mapping dictionaries**: Track character-to-word and word-to-character mappings
70+
4. **Verify bijection**: Ensure each character maps to exactly one word and vice versa
71+
72+
**Brute force vs. optimized strategy:**
73+
- **Brute force**: Try all possible mappings. This is extremely inefficient.
74+
- **Optimized**: Use hash tables to track mappings in a single pass. This takes O(n) time.
75+
76+
### Steps
77+
Let's walk through the solution step by step using the first example: `pattern = "abba"`, `s = "dog cat cat dog"`
78+
79+
**Step 1: Split the string into words**
80+
- `s = "dog cat cat dog"`
81+
- `words = ["dog", "cat", "cat", "dog"]`
82+
83+
**Step 2: Check length consistency**
84+
- `pattern.length = 4`
85+
- `words.length = 4`
86+
- Lengths match ✓
87+
88+
**Step 3: Initialize mapping dictionaries**
89+
- `char_to_word = {}` (maps pattern characters to words)
90+
- `word_to_char = {}` (maps words to pattern characters)
91+
92+
**Step 4: Check first character-word pair**
93+
- `pattern[0] = 'a'`, `words[0] = "dog"`
94+
- Check if 'a' is already mapped: No
95+
- Check if "dog" is already mapped: No
96+
- Add mappings: `char_to_word['a'] = "dog"`, `word_to_char["dog"] = 'a'`
97+
98+
**Step 5: Check second character-word pair**
99+
- `pattern[1] = 'b'`, `words[1] = "cat"`
100+
- Check if 'b' is already mapped: No
101+
- Check if "cat" is already mapped: No
102+
- Add mappings: `char_to_word['b'] = "cat"`, `word_to_char["cat"] = 'b'`
103+
104+
**Step 6: Check third character-word pair**
105+
- `pattern[2] = 'b'`, `words[2] = "cat"`
106+
- Check if 'b' is already mapped: Yes, to "cat"
107+
- Verify consistency: `char_to_word['b'] == "cat"`
108+
- Check if "cat" is already mapped: Yes, to 'b'
109+
- Verify consistency: `word_to_char["cat"] == 'b'`
110+
111+
**Step 7: Check fourth character-word pair**
112+
- `pattern[3] = 'a'`, `words[3] = "dog"`
113+
- Check if 'a' is already mapped: Yes, to "dog"
114+
- Verify consistency: `char_to_word['a'] == "dog"`
115+
- Check if "dog" is already mapped: Yes, to 'a'
116+
- Verify consistency: `word_to_char["dog"] == 'a'`
117+
118+
**Step 8: Result**
119+
- All character-word pairs are consistent
120+
- Pattern is followed: `true`
121+
122+
**Why this works:**
123+
By maintaining mappings in both directions, we ensure that:
124+
1. Each character in the pattern maps to exactly one word
125+
2. Each word maps to exactly one character
126+
3. The bijection property is maintained throughout the pattern
127+
128+
> **Note:** The key insight is using bidirectional mapping to ensure the bijection property. This is similar to the isomorphic strings problem but operates on words instead of individual characters.
129+
130+
**Time Complexity:** O(n) - we visit each character/word once
131+
**Space Complexity:** O(k) - where k is the number of unique characters/words

solutions/290/01.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
def wordPattern(pattern, s):
2+
"""
3+
Determine if the string s follows the given pattern.
4+
5+
Args:
6+
pattern: str - The pattern string to match against
7+
s: str - The string of space-separated words
8+
9+
Returns:
10+
bool - True if s follows the pattern, False otherwise
11+
"""
12+
# Split the string into words
13+
words = s.split()
14+
15+
# Check if pattern length matches word count
16+
if len(pattern) != len(words):
17+
return False
18+
19+
# Create mapping dictionaries for both directions
20+
char_to_word = {} # maps pattern characters to words
21+
word_to_char = {} # maps words to pattern characters
22+
23+
# Check each character-word pair
24+
for i in range(len(pattern)):
25+
char = pattern[i]
26+
word = words[i]
27+
28+
# Check if char is already mapped
29+
if char in char_to_word:
30+
# Verify the mapping is consistent
31+
if char_to_word[char] != word:
32+
return False
33+
else:
34+
# Check if word is already mapped to by another character
35+
if word in word_to_char:
36+
return False
37+
38+
# Add new mapping
39+
char_to_word[char] = word
40+
word_to_char[word] = char
41+
42+
return True

0 commit comments

Comments
 (0)