HomeLeetcode290. Word Pattern - Leetcode Solutions

290. Word Pattern – Leetcode Solutions

Description

Given a pattern and a string s, find if s follows the same pattern.

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:

  • Each letter in pattern maps to exactly one unique word in s.
  • Each unique word in s maps to exactly one letter in pattern.
  • No two letters map to the same word, and no two words map to the same letter.

Examples:

Example 1:

Input: pattern = "abba", s = "dog cat cat dog"

Output: true

Explanation:

The bijection can be established as:

'a' maps to "dog".
'b' maps to "cat".

Example 2:

Input: pattern = "abba", s = "dog cat cat fish"

Output: false

Example 3:

Input: pattern = "aaaa", s = "dog cat cat dog"

Output: false

Solution in Python

Python
class Solution:
    def wordPattern(self, pattern: str, s: str) -> bool:
        # Split the string 's' into a list of words
        words = s.split()
        
        # If the lengths of pattern and words do not match, it cannot follow the pattern
        if len(pattern) != len(words):
            return False
        
        # Dictionary to map letters from pattern to words
        pattern_to_word = {}
        
        # Dictionary to map words to letters from pattern (for checking bijection)
        word_to_pattern = {}
        
        # Iterate over both the pattern and corresponding words simultaneously
        for p, word in zip(pattern, words):
            # Check if there is already a mapping from pattern to word
            if p in pattern_to_word:
                # If the current mapping does not match the word, return False
                if pattern_to_word[p] != word:
                    return False
            else:
                # Check if the word is already mapped to a different letter
                if word in word_to_pattern:
                    return False
                # Create new mappings in both dictionaries
                pattern_to_word[p] = word
                word_to_pattern[word] = p
        
        # If all checks passed, return True
        return True

Detailed Explanation:

  1. Splitting the String s:
    • We split the input string s into a list of words using split(), which breaks the string by spaces.
  2. Length Mismatch Check:
    • If the number of characters in pattern doesn’t match the number of words in s, it’s impossible to establish a bijection. In that case, we return False.
  3. Two Dictionaries:
    • We create two dictionaries:
      • pattern_to_word: Maps each character in pattern to a corresponding word in s.
      • word_to_pattern: Maps each word in s back to the corresponding character in pattern. This helps ensure the bijection (one-to-one mapping) is maintained.
  4. Iterating through the Pattern and Words:
    • We use the zip function to iterate through both pattern and words simultaneously.
    • For each pair (p, word):
      • If p (the character from pattern) is already mapped to a word, we check if it matches the current word. If not, return False.
      • If the word is already mapped to a different letter (in word_to_pattern), return False.
      • If no mapping exists, we create new mappings in both dictionaries.
  5. Return True:
    • If the loop completes without any inconsistencies, return True, indicating that the string s follows the same pattern.

This approach ensures that we maintain a bijection between characters in pattern and words in s. The time complexity is O(n), where n is the length of pattern, since we loop through both the pattern and s once.

Solution in C++

C++
#include <unordered_map>
#include <sstream>
#include <vector>
#include <string>

class Solution {
public:
    bool wordPattern(std::string pattern, std::string s) {
        // Split the string s into words
        std::istringstream stream(s);
        std::vector<std::string> words;
        std::string word;

        // Read words from the string stream into the words vector
        while (stream >> word) {
            words.push_back(word);
        }

        // If the length of the pattern does not match the number of words, return false
        if (pattern.length() != words.size()) {
            return false;
        }

        // Maps to establish the one-to-one relationship
        std::unordered_map<char, std::string> patternToWord;
        std::unordered_map<std::string, char> wordToPattern;

        // Iterate over the pattern and the words simultaneously
        for (int i = 0; i < pattern.length(); ++i) {
            char p = pattern[i];
            const std::string& w = words[i];

            // Check if there's already a mapping for the character in the pattern
            if (patternToWord.count(p)) {
                // If the current mapping does not match the expected word, return false
                if (patternToWord[p] != w) {
                    return false;
                }
            } else {
                // If the character is not mapped yet, check if the word is already mapped
                if (wordToPattern.count(w)) {
                    return false; // The word is already associated with a different character
                }
                // Create new mappings in both dictionaries
                patternToWord[p] = w;
                wordToPattern[w] = p;
            }
        }

        // If all checks are passed, the pattern matches the string
        return true;
    }
};

Solution in Javascript

JavaScript
var wordPattern = function(pattern, s) {
    // Split the string 's' into an array of words
    const words = s.split(' ');

    // If the length of pattern does not match the number of words, return false
    if (pattern.length !== words.length) {
        return false;
    }

    // Create two maps to establish the one-to-one relationship
    const patternToWord = new Map();
    const wordToPattern = new Map();

    // Iterate through the pattern and corresponding words simultaneously
    for (let i = 0; i < pattern.length; i++) {
        const p = pattern[i];        // Current character in the pattern
        const word = words[i];       // Corresponding word from the array

        // Check if there is already a mapping for the character in the pattern
        if (patternToWord.has(p)) {
            // If the current mapping does not match the expected word, return false
            if (patternToWord.get(p) !== word) {
                return false;
            }
        } else {
            // If the character is not mapped yet, check if the word is already mapped
            if (wordToPattern.has(word)) {
                return false; // The word is already associated with a different character
            }
            // Create new mappings in both maps
            patternToWord.set(p, word);
            wordToPattern.set(word, p);
        }
    }

    // If all checks passed, the pattern matches the string
    return true;
};

Solution in Java

Java
import java.util.HashMap;
import java.util.Map;

class Solution {
    public boolean wordPattern(String pattern, String s) {
        // Split the string 's' into an array of words
        String[] words = s.split(" ");

        // If the length of pattern does not match the number of words, return false
        if (pattern.length() != words.length) {
            return false;
        }

        // Create two maps to establish the one-to-one relationship
        Map<Character, String> patternToWord = new HashMap<>();
        Map<String, Character> wordToPattern = new HashMap<>();

        // Iterate through the pattern and corresponding words simultaneously
        for (int i = 0; i < pattern.length(); i++) {
            char p = pattern.charAt(i); // Current character in the pattern
            String word = words[i];      // Corresponding word from the array

            // Check if there is already a mapping for the character in the pattern
            if (patternToWord.containsKey(p)) {
                // If the current mapping does not match the expected word, return false
                if (!patternToWord.get(p).equals(word)) {
                    return false;
                }
            } else {
                // If the character is not mapped yet, check if the word is already mapped
                if (wordToPattern.containsKey(word)) {
                    return false; // The word is already associated with a different character
                }
                // Create new mappings in both maps
                patternToWord.put(p, word);
                wordToPattern.put(word, p);
            }
        }

        // If all checks passed, the pattern matches the string
        return true;
    }
}

Subscribe
Notify of

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Popular