Articles by FavTutor
  • AI News
  • Data Structures
  • Web Developement
  • AI Code GeneratorNEW
  • Student Help
  • Main Website
No Result
View All Result
FavTutor
  • AI News
  • Data Structures
  • Web Developement
  • AI Code GeneratorNEW
  • Student Help
  • Main Website
No Result
View All Result
Articles by FavTutor
No Result
View All Result
Home Data Structures and Algorithms

Word Search II Problem (C++, Java, Python)

Jatin Chanana by Jatin Chanana
November 28, 2023
Reading Time: 9 mins read
word search ii leetcode problem
Follow us on Google News   Subscribe to our newsletter

In the world of computer programming, word search puzzles have always been a popular and challenging game to solve. The task of finding words in a grid of letters has fascinated both enthusiasts and developers alike. In this article, we will explore the concept of word search, and discuss an approach to solve the ‘word search II’ leetcode problem.

What is the Word Search II Problem?

The goal of the classic problem word search II is to locate a list of given words that are hidden within a grid of letters. The words can be spelled forward or backward and arranged horizontally, vertically, or diagonally. Each letter in the grid can only be used once to form a word, the main task is to identify words from a jumble of letters and mark them as found.

Let us take an example to understand clearly:

Input:  
words = [“fav”, “tutor”, “pear”]
board = [
[‘t’, ‘u’, ‘a’, ‘p’],
[‘f’, ‘t’, ‘o’, ‘r’  ],
[‘a’, ‘v’, ‘p’, ‘r’],
[‘l’, ‘l’, ‘e’, ‘v’  ] ]

Output:
[“fav”, “tutor”]

In this example, we have a 2D board and a list of words. The task is to find all the words from the list that can be constructed using the letters on the board. In this case, the words “fav” and “tutor” can be found on the board.

example of word search ii

Backtracking Approach: Using Trie

Solving the Word Search II problem using backtracking efficiently involves using the Trie data structure to store the list of words. The Trie data structure allows us to build a hierarchical representation of the list words. Each node in the Trie represents a letter, and the paths from the root to the nodes form words.

We will follow the given steps to solve this problem:

  • Create a Trie data structure and insert all the words from the list into the Trie.
creating a trie
  • Iterate over each cell in the 2D board and perform a depth-first search (DFS) starting from that cell.
  • In the DFS, check if the current letter in the board exists in the Trie. If it does, move to the next letter and continue the DFS recursively.
  • If we reach a node in the Trie that represents the end of a word, add that word to the result list.
  • Keep track of visited cells to avoid reusing the same letter in a word.
Applying DFS
  • Repeat the DFS for each cell on the board.
  • After completing the DFS for a cell, mark it as unvisited to allow other paths to use it.

C++ Code

Below is the C++ program to solve Word Search II problem:

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

class TrieNode {
public:
    unordered_map<char, TrieNode*> children;
    bool isEnd;

    TrieNode() : isEnd(false) {}
};

class Trie {
public:
    TrieNode* root;

    Trie() : root(new TrieNode()) {}

    void insert(const string& word) {
        TrieNode* node = root;
        for (char c : word) {
            if (!node->children.count(c)) {
                node->children[c] = new TrieNode();
            }
            node = node->children[c];
        }
        node->isEnd = true;
    }
};

class Solution {
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        Trie trie;
        for (const string& word : words) {
            trie.insert(word);
        }

        vector<string> result;
        int m = board.size();
        int n = board[0].size();

        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                dfs(board, trie.root, i, j, "", result);
            }
        }

        return result;
    }

private:
    void dfs(vector<vector<char>>& board, TrieNode* node, int i, int j, string path, vector<string>& result) {
        char c = board[i][j];
        if (!node->children.count(c)) {
            return; // Stop DFS if the current path is not a prefix of any word
        }

        node = node->children[c];
        if (node->isEnd) {
            result.push_back(path + c);
            node->isEnd = false; // Remove the word from the Trie to avoid duplicates
        }

        board[i][j] = '#'; // Mark the cell as visited

        // Explore neighbors in all directions
        static const vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        for (const auto& dir : directions) {
            int ni = i + dir.first;
            int nj = j + dir.second;
            if (ni >= 0 && ni < board.size() && nj >= 0 && nj < board[0].size() && board[ni][nj] != '#') {
                dfs(board, node, ni, nj, path + c, result);
            }
        }

        board[i][j] = c; // Restore the cell to its original state
    }
};

int main() {
    Solution solution;
    vector<string> words = {"fav", "tutor", "pear"};
    vector<vector<char>> board = {
        {'t', 'u', 'a', 'p'},
        {'f', 't', 'o', 'r'},
        {'a', 'v', 'p', 'r'},
        {'l', 'l', 'e', 'v'}
    };

    vector<string> result = solution.findWords(board, words);

    cout << "Output: [";
    for (int i = 0; i < result.size(); ++i) {
        cout << "\"" << result[i] << "\"";
        if (i < result.size() - 1) {
            cout << ", ";
        }
    }
    cout << "]" << endl;

    return 0;
}

Python Code

Below is the Python program to solve the Word Search II problem:

from typing import List

class TrieNode:
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.isEnd = True

class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        trie = Trie()
        for word in words:
            trie.insert(word)

        result = []
        m, n = len(board), len(board[0])

        def dfs(node, i, j, path):
            nonlocal board, result

            if i < 0 or i >= m or j < 0 or j >= n or board[i][j] == '#' or board[i][j] not in node.children:
                return

            char = board[i][j]
            node = node.children[char]

            if node.isEnd:
                result.append(path + char)
                node.isEnd = False  # Remove the word from the Trie to avoid duplicates

            board[i][j] = '#'  # Mark the cell as visited

            directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
            for x, y in directions:
                ni, nj = i + x, j + y
                dfs(node, ni, nj, path + char)

            board[i][j] = char  # Restore the cell to its original state

        for i in range(m):
            for j in range(n):
                dfs(trie.root, i, j, "")

        return result

if __name__ == "__main__":
    solution = Solution()
    words = ["fav", "tutor", "pear"]
    board = [
        ['t', 'u', 'a', 'p'],
        ['f', 't', 'o', 'r'],
        ['a', 'v', 'p', 'r'],
        ['l', 'l', 'e', 'v']
    ]

    result = solution.findWords(board, words)

    print("Output:", result)

Java Code

Below is the Java program to solve it:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class TrieNode {
    Map<Character, TrieNode> children;
    boolean isEnd;

    TrieNode() {
        children = new HashMap<>();
        isEnd = false;
    }
}

class Trie {
    TrieNode root;

    Trie() {
        root = new TrieNode();
    }

    void insert(String word) {
        TrieNode node = root;
        for (char c : word.toCharArray()) {
            if (!node.children.containsKey(c)) {
                node.children.put(c, new TrieNode());
            }
            node = node.children.get(c);
        }
        node.isEnd = true;
    }
}

public class WordSearchII {
    public List<String> findWords(char[][] board, String[] words) {
        Trie trie = new Trie();
        for (String word : words) {
            trie.insert(word);
        }

        List<String> result = new ArrayList<>();
        int m = board.length;
        int n = board[0].length;

        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                dfs(board, trie.root, i, j, "", result);
            }
        }

        return result;
    }

    private void dfs(char[][] board, TrieNode node, int i, int j, String path, List<String> result) {
        if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] == '#' || !node.children.containsKey(board[i][j])) {
            return;
        }

        char c = board[i][j];
        node = node.children.get(c);

        if (node.isEnd) {
            result.add(path + c);
            node.isEnd = false; // Remove the word from the Trie to avoid duplicates
        }

        board[i][j] = '#'; // Mark the cell as visited

        int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        for (int[] dir : directions) {
            int ni = i + dir[0];
            int nj = j + dir[1];
            dfs(board, node, ni, nj, path + c, result);
        }

        board[i][j] = c; // Restore the cell to its original state
    }

    public static void main(String[] args) {
        WordSearchII wordSearch = new WordSearchII();
        String[] words = {"fav", "tutor", "pear"};
        char[][] board = {
                {'t', 'u', 'a', 'p'},
                {'f', 't', 'o', 'r'},
                {'a', 'v', 'p', 'r'},
                {'l', 'l', 'e', 'v'}
        };

        List<String> result = wordSearch.findWords(board, words);

        System.out.print("Output: [");
        for (int i = 0; i < result.size(); ++i) {
            System.out.print("\"" + result.get(i) + "\"");
            if (i < result.size() - 1) {
                System.out.print(", ");
            }
        }
        System.out.println("]");
    }
}

Output:

Output: ["tutor", "fav"]

Complexity Analysis

Let’s look at the time and space complexity of the same.

For each word in the words array, the code inserts it into the Trie. The insertion operation takes O(L) time, where L is the length of the word.

  • If there are N words and the average length of words is M, the total time complexity for inserting all words into the Trie is O(N * M).
  • The code performs a Depth-First Search (DFS) on the board starting from each cell. In the worst case, it explores all possible paths on the board.
  • For each cell, the DFS explores four neighboring cells (up, down, left, right).


Therefore, the DFS can take up to O(4^(m*n)) (m&n are board dimensions) time in the worst case.

Total Time Complexity is O(4^(m*n)).

  • The space required for the Trie depends on the number and length of words. In the worst case, where there are N words with an average length of M, the space complexity is O(N * M).
  • The DFS is performed recursively, and the maximum depth of recursion is the maximum possible path length on the board.
  • The maximum depth is O(m * n) in the worst case (when exploring all cells on the board)

The overall space complexity is dominated by the Trie, so it is O(N * M).

Conclusion

In this article, we explored the concept of word search II problem from leetcode and discussed an optimized approach to solve this problem using a trie data structure. The Trie approach leverages the hierarchical structure of the Trie to perform fast searches and provides an elegant solution to the word search II problem.

ShareTweetShareSendSend
Jatin Chanana

Jatin Chanana

I am Jatin, a final-year undergraduate student with a keen interest in the field of software development. I possess a strong academic background and a deep passion for Data Structures, Algorithms, and Web Development.

RelatedPosts

validate ip address

Validate IP Address Problem ( C++, JAVA, Python)

April 3, 2025
Shortest Palindrome Problem

Shortest Palindrome Problem ( C++, JAVA, Python)

April 4, 2025
Zigzag Conversion Problem

Zigzag Conversion Problem (C++, Java, Python)

April 4, 2025
Next Right Pointers In Each Node

Populating Next Right Pointers In Each Node (with code)

March 27, 2024
Coin Change II

Coin Change II Problem (C++, Java, Python)

April 7, 2025

About FavTutor

FavTutor is a trusted online tutoring service to connects students with expert tutors to provide guidance on Computer Science subjects like Java, Python, C, C++, SQL, Data Science, Statistics, etc.

Categories

  • AI News, Research & Latest Updates
  • Trending
  • Data Structures
  • Web Developement
  • Data Science

Important Subjects

  • Python Assignment Help
  • C++ Help
  • R Programming Help
  • Java Homework Help
  • Programming Help

Resources

  • About Us
  • Contact Us
  • Editorial Policy
  • Privacy Policy
  • Terms and Conditions

Website listed on Ecomswap. © Copyright 2025 All Rights Reserved.

No Result
View All Result
  • AI News
  • Data Structures
  • Web Developement
  • AI Code Generator
  • Student Help
  • Main Website

Website listed on Ecomswap. © Copyright 2025 All Rights Reserved.