Skip to content

Enhance class & function documentation in WordSearch.java #5578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Oct 7, 2024
Merged
92 changes: 61 additions & 31 deletions src/main/java/com/thealgorithms/backtracking/WordSearch.java
Original file line number Diff line number Diff line change
@@ -1,51 +1,72 @@
package com.thealgorithms.backtracking;

/*
Word Search Problem (https://en.wikipedia.org/wiki/Word_search)

Given an m x n grid of characters board and a string word, return true if word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are
those horizontally or vertically neighboring. The same letter cell may not be used more than once.

For example,
Given board =

[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.
*/

/*
Solution
Depth First Search in matrix (as multiple sources possible) with backtracking
like finding cycle in a directed graph. Maintain a record of path

Tx = O(m * n * 3^L): for each cell, we look at 3 options (not 4 as that one will be visited), we
do it L times Sx = O(L) : stack size is max L
*/

/**
* Word Search Problem
*
* This class solves the word search problem where given an m x n grid of characters (board)
* and a target word, the task is to check if the word exists in the grid.
* The word can be constructed from sequentially adjacent cells (horizontally or vertically),
* and the same cell may not be used more than once in constructing the word.
*
* Example:
* - For board =
* [
* ['A','B','C','E'],
* ['S','F','C','S'],
* ['A','D','E','E']
* ]
* and word = "ABCCED", -> returns true
* and word = "SEE", -> returns true
* and word = "ABCB", -> returns false
*
* Solution:
* - Depth First Search (DFS) with backtracking is used to explore possible paths from any cell
* matching the first letter of the word. DFS ensures that we search all valid paths, while
* backtracking helps in reverting decisions when a path fails to lead to a solution.
*
* Time Complexity: O(m * n * 3^L)
* - m = number of rows in the board
* - n = number of columns in the board
* - L = length of the word
* - For each cell, we look at 3 possible directions (since we exclude the previously visited direction),
* and we do this for L letters.
*
* Space Complexity: O(L)
* - Stack space for the recursive DFS function, where L is the maximum depth of recursion (length of the word).
*/
public class WordSearch {
private final int[] dx = {0, 0, 1, -1};
private final int[] dy = {1, -1, 0, 0};
private boolean[][] visited;
private char[][] board;
private String word;

/**
* Checks if the given (x, y) coordinates are valid positions in the board.
*
* @param x The row index.
* @param y The column index.
* @return True if the coordinates are within the bounds of the board; false otherwise.
*/
private boolean isValid(int x, int y) {
return x >= 0 && x < board.length && y >= 0 && y < board[0].length;
}

/**
* Performs Depth First Search (DFS) from the cell (x, y)
* to search for the next character in the word.
*
* @param x The current row index.
* @param y The current column index.
* @param nextIdx The index of the next character in the word to be matched.
* @return True if a valid path is found to match the remaining characters of the word; false otherwise.
*/
private boolean doDFS(int x, int y, int nextIdx) {
visited[x][y] = true;
if (nextIdx == word.length()) {
return true;
}

for (int i = 0; i < 4; ++i) {
int xi = x + dx[i];
int yi = y + dy[i];
Expand All @@ -56,10 +77,19 @@ private boolean doDFS(int x, int y, int nextIdx) {
}
}
}
visited[x][y] = false;

visited[x][y] = false; // Backtrack
return false;
}

/**
* Main function to check if the word exists in the board. It initiates DFS from any
* cell that matches the first character of the word.
*
* @param board The 2D grid of characters (the board).
* @param word The target word to search for in the board.
* @return True if the word exists in the board; false otherwise.
*/
public boolean exist(char[][] board, String word) {
this.board = board;
this.word = word;
Expand Down