LeetCode //C - 212. Word Search II

Given an m x n board of characters and a list of strings words , return all words on the board.

Each word must be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

Example 1:

Input: board = \["o","a","a","n","e","t","a","e","i","h","k","r","i","f","l","v"], words = "oath","pea","eat","rain"
Output: "eat","oath"

Example 2:

Input: board = \["a","b","c","d"], words = "abcb"
Output: \[\]

Constraints:
  • m == board.length
  • n == boardi.length
  • 1 <= m, n <= 12
  • boardij is a lowercase English letter.
  • 1 <= words.length <= 3 ∗ 1 0 4 3 * 10^4 3∗104
  • 1 <= wordsi.length <= 10
  • wordsi consists of lowercase English letters.
  • All the strings of words are unique.

From: LeetCode

Link: 212. Word Search II


Solution:

Ideas:

Trie (Prefix Tree):

A Trie is a tree-like data structure that is used to store a dynamic set of strings. Tries are particularly useful for searches in dictionaries with a large number of words. Each node of the Trie represents a single character of a word, and the path from the root node to any node in the tree represents the prefix (part of a word) associated with that node.

Benefits of Trie:

  1. Provides efficient word insertions and lookups.
  2. Allows us to search for a word prefix efficiently.

DFS Backtracking:

Backtracking is a general algorithm used to find all (or some) solutions to computational problems by incrementally building candidates towards solutions and abandoning a candidate as soon as it is determined that it cannot be extended to a valid solution.

In the context of this problem, we use backtracking to traverse the board starting from each cell. For each cell, we explore in all four possible directions (up, down, left, right) to see if we can form a word present in the Trie.

Solution Steps:

  1. Building the Trie:
  • All the words in the words array are inserted into a Trie.
  • Each node in the Trie has 26 pointers (for each lowercase English letter) and a word pointer which points to the word if that node marks the end of a valid word.
  1. DFS Search on Board:
  • We iterate over each cell of the board.
  • Starting from each cell, we perform a DFS search to build words and check if they are in the Trie.
  • While traversing, if the current sequence of characters doesn't match any prefix in the Trie, we backtrack (return from the recursion).
  • If we find a valid word (by reaching a Trie node that has a non-null word pointer), we add that word to the results.
  1. Optimization:
  • Once a word is found, we nullify the word pointer in the Trie node to ensure that the same word is not added multiple times.
Code:
c 复制代码
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

typedef struct TrieNode {
    struct TrieNode *children[26];
    char *word;
} TrieNode;

TrieNode* createNode() {
    TrieNode *node = malloc(sizeof(TrieNode));
    for (int i = 0; i < 26; i++) {
        node->children[i] = NULL;
    }
    node->word = NULL;
    return node;
}

void insert(TrieNode *root, char *word) {
    TrieNode *node = root;
    for (int i = 0; word[i]; i++) {
        int index = word[i] - 'a';
        if (!node->children[index]) {
            node->children[index] = createNode();
        }
        node = node->children[index];
    }
    node->word = word;
}

void backtrack(char **board, int boardSize, int* boardColSize, TrieNode *node, int i, int j, char **result, int *returnSize) {
    if (i < 0 || i >= boardSize || j < 0 || j >= boardColSize[i] || board[i][j] == '#') {
        return;
    }
    
    char c = board[i][j];
    if (!node->children[c - 'a']) {
        return;
    }

    node = node->children[c - 'a'];
    if (node->word) {
        result[*returnSize] = node->word;
        (*returnSize)++;
        node->word = NULL; // To avoid duplication
    }

    board[i][j] = '#';  // Mark as visited
    backtrack(board, boardSize, boardColSize, node, i+1, j, result, returnSize);
    backtrack(board, boardSize, boardColSize, node, i-1, j, result, returnSize);
    backtrack(board, boardSize, boardColSize, node, i, j+1, result, returnSize);
    backtrack(board, boardSize, boardColSize, node, i, j-1, result, returnSize);
    board[i][j] = c;    // Revert back
}

char** findWords(char** board, int boardSize, int* boardColSize, char **words, int wordsSize, int* returnSize) {
    TrieNode *root = createNode();
    for (int i = 0; i < wordsSize; i++) {
        insert(root, words[i]);
    }
    
    char **result = malloc(wordsSize * sizeof(char*));
    *returnSize = 0;

    for (int i = 0; i < boardSize; i++) {
        for (int j = 0; j < boardColSize[i]; j++) {
            backtrack(board, boardSize, boardColSize, root, i, j, result, returnSize);
        }
    }

    return result;
}
相关推荐
Cccp.1232 小时前
【leetcode】(七)前缀树和贪心算法
数据结构·leetcode·贪心算法
千里码aicood2 小时前
基于CART算法的图书分类系统设计与实现
数据库·算法·分类
做cv的小昊3 小时前
【World Model】π0.5:a Vision-Language-Action Model with Open-World Generalization
人工智能·算法·机器学习·大模型·多模态·vla·世界模型
لا معنى له3 小时前
World-In-World: World Models in a Closed-Loop World
算法
@yanyu6665 小时前
C编译器安装与第一个C程序
c语言·开发语言
山下梅子酒2255 小时前
洛谷-入门-B2070
c语言
Logic1015 小时前
C语言/数据结构位运算题解:异或XOR找出多任务下载器中的“独特下载速度“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Discipline10296 小时前
尼泊尔河流流量:天气驱动的预测与高流量风险
人工智能·算法
XuCoder6 小时前
改一个数,右边全得重算,这题怎么扛住两万次查询
算法