174 lines
8.1 KiB
YAML
174 lines
8.1 KiB
YAML
title: Check if the Sentence Is Pangram
|
|
slug: check-if-the-sentence-is-pangram
|
|
difficulty: easy
|
|
leetcode_id: 1832
|
|
leetcode_url: https://leetcode.com/problems/check-if-the-sentence-is-pangram/
|
|
categories:
|
|
- strings
|
|
- hash-tables
|
|
patterns:
|
|
- prefix-sum
|
|
|
|
function_signature: "def check_if_pangram(sentence: str) -> bool:"
|
|
|
|
test_cases:
|
|
visible:
|
|
- input: { sentence: "thequickbrownfoxjumpsoverthelazydog" }
|
|
expected: true
|
|
- input: { sentence: "leetcode" }
|
|
expected: false
|
|
hidden:
|
|
- input: { sentence: "abcdefghijklmnopqrstuvwxyz" }
|
|
expected: true
|
|
- input: { sentence: "a" }
|
|
expected: false
|
|
- input: { sentence: "abcdefghijklmnopqrstuvwxy" }
|
|
expected: false
|
|
- input: { sentence: "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz" }
|
|
expected: true
|
|
- input: { sentence: "zyxwvutsrqponmlkjihgfedcba" }
|
|
expected: true
|
|
- input: { sentence: "qwertyuiopasdfghjklzxcvbnm" }
|
|
expected: true
|
|
|
|
description: |
|
|
A **pangram** is a sentence where every letter of the English alphabet appears at least once.
|
|
|
|
Given a string `sentence` containing only lowercase English letters, return `true` *if* `sentence` *is a **pangram**, or* `false` *otherwise*.
|
|
|
|
constraints: |
|
|
- `1 <= sentence.length <= 1000`
|
|
- `sentence` consists of lowercase English letters.
|
|
|
|
examples:
|
|
- input: 'sentence = "thequickbrownfoxjumpsoverthelazydog"'
|
|
output: "true"
|
|
explanation: "sentence contains at least one of every letter of the English alphabet."
|
|
- input: 'sentence = "leetcode"'
|
|
output: "false"
|
|
explanation: "The sentence only contains 5 unique letters: c, d, e, l, o, t. It's missing 21 letters."
|
|
|
|
explanation:
|
|
intuition: |
|
|
Think of this problem like a checklist: you have 26 boxes, one for each letter of the alphabet from 'a' to 'z'. As you read through the sentence, you're checking off each letter you encounter.
|
|
|
|
The question becomes: **after reading the entire sentence, have all 26 boxes been checked?**
|
|
|
|
A **set** is the perfect data structure for this task. Sets automatically handle duplicates — if you add the same letter multiple times, it only appears once. So as you iterate through the sentence, you add each character to a set. At the end, if the set contains exactly 26 unique characters, you have a pangram.
|
|
|
|
The key insight is that we don't care *how many times* each letter appears, just *whether* it appears at all. This makes the problem a simple membership check rather than a counting problem.
|
|
|
|
approach: |
|
|
We solve this using a **Set-Based Approach**:
|
|
|
|
**Step 1: Create a set from the sentence**
|
|
|
|
- Convert the sentence into a set of characters
|
|
- This automatically removes duplicates, leaving only unique letters
|
|
- In Python, this is as simple as `set(sentence)`
|
|
|
|
|
|
|
|
**Step 2: Check the size of the set**
|
|
|
|
- If the set contains exactly 26 elements, every letter of the alphabet is present
|
|
- Return `True` if `len(unique_chars) == 26`, otherwise `False`
|
|
|
|
|
|
|
|
This approach works because the problem guarantees the input contains only lowercase English letters. Since there are exactly 26 such letters, a set of size 26 means all letters are present.
|
|
|
|
common_pitfalls:
|
|
- title: Using a List Instead of a Set
|
|
description: |
|
|
A common mistake is to use a list to track seen characters and check membership with `if char not in seen_list`. While this works, it's inefficient.
|
|
|
|
List membership checking is **O(n)** per operation, making the overall algorithm **O(n * m)** where m is the number of unique characters seen. With a set, membership checking is **O(1)** on average, keeping the algorithm at **O(n)**.
|
|
|
|
For this problem's constraints (n <= 1000), the difference is negligible. But using sets is a good habit for larger inputs.
|
|
wrong_approach: "List with linear membership checking"
|
|
correct_approach: "Set with O(1) membership checking"
|
|
|
|
- title: Hardcoding the Alphabet
|
|
description: |
|
|
Some solutions compare the set against a hardcoded string like `"abcdefghijklmnopqrstuvwxyz"`. While this works, it's error-prone (easy to miss or duplicate a letter) and less elegant.
|
|
|
|
Since we know there are exactly 26 lowercase English letters and the input is guaranteed to contain only those letters, simply checking `len(set(sentence)) == 26` is cleaner and less bug-prone.
|
|
wrong_approach: "Comparing against hardcoded alphabet string"
|
|
correct_approach: "Check if set size equals 26"
|
|
|
|
- title: Forgetting About Case Sensitivity
|
|
description: |
|
|
While this problem specifies lowercase-only input, in real-world pangram checking you'd need to handle mixed case. A sentence like "The Quick Brown Fox..." would fail if you don't convert to lowercase first.
|
|
|
|
Always read the constraints carefully. Here, the guarantee of lowercase-only input simplifies our solution.
|
|
|
|
key_takeaways:
|
|
- "**Sets for uniqueness**: When you only care about *presence* (not count), sets provide O(1) lookup and automatic deduplication"
|
|
- "**Know your alphabet**: The English alphabet has exactly 26 letters — this fixed constant enables the simple `len() == 26` check"
|
|
- "**Read the constraints**: The lowercase-only guarantee eliminates the need for case conversion"
|
|
- "**Pattern recognition**: This is a classic 'check completeness' pattern — useful for problems asking if all elements of a known set are present"
|
|
|
|
time_complexity: "O(n). We iterate through each character in the sentence once to build the set, where n is the length of the sentence."
|
|
space_complexity: "O(1). The set can contain at most 26 characters (the English alphabet), which is a constant regardless of input size."
|
|
|
|
solutions:
|
|
- approach_name: Set Conversion
|
|
is_optimal: true
|
|
code: |
|
|
def check_if_pangram(sentence: str) -> bool:
|
|
# Convert sentence to set of unique characters
|
|
unique_chars = set(sentence)
|
|
|
|
# Pangram if all 26 letters are present
|
|
return len(unique_chars) == 26
|
|
explanation: |
|
|
**Time Complexity:** O(n) — Single pass to build the set.
|
|
|
|
**Space Complexity:** O(1) — At most 26 characters in the set.
|
|
|
|
This is the most Pythonic solution. The `set()` constructor iterates through the string once, and checking the length is O(1). Clean, readable, and efficient.
|
|
|
|
- approach_name: Boolean Array
|
|
is_optimal: true
|
|
code: |
|
|
def check_if_pangram(sentence: str) -> bool:
|
|
# Track which letters we've seen (index 0 = 'a', index 25 = 'z')
|
|
seen = [False] * 26
|
|
|
|
for char in sentence:
|
|
# Convert character to index: 'a' -> 0, 'b' -> 1, etc.
|
|
index = ord(char) - ord('a')
|
|
seen[index] = True
|
|
|
|
# Pangram if all 26 positions are True
|
|
return all(seen)
|
|
explanation: |
|
|
**Time Complexity:** O(n) — Single pass through the sentence.
|
|
|
|
**Space Complexity:** O(1) — Fixed array of 26 booleans.
|
|
|
|
This approach uses a boolean array instead of a set. It's useful to understand as it shows how to map characters to array indices using `ord()`. The `all()` function returns `True` only if every element is `True`.
|
|
|
|
- approach_name: Bitmask
|
|
is_optimal: true
|
|
code: |
|
|
def check_if_pangram(sentence: str) -> bool:
|
|
# Use a 32-bit integer as a bitmask
|
|
# Bit 0 represents 'a', bit 1 represents 'b', etc.
|
|
seen = 0
|
|
|
|
for char in sentence:
|
|
# Set the bit corresponding to this character
|
|
bit_position = ord(char) - ord('a')
|
|
seen |= (1 << bit_position)
|
|
|
|
# Check if all 26 bits are set: 2^26 - 1 = 67108863
|
|
return seen == (1 << 26) - 1
|
|
explanation: |
|
|
**Time Complexity:** O(n) — Single pass through the sentence.
|
|
|
|
**Space Complexity:** O(1) — Single integer variable.
|
|
|
|
This advanced technique uses bit manipulation to track seen letters. Each bit in the integer represents whether a letter has been seen. The expression `(1 << 26) - 1` creates a number with 26 one-bits, representing all letters present. This is the most space-efficient approach and demonstrates bitmasking patterns.
|