• LeetCode //C - 212. Word Search II


    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 == board[i].length
    • 1 <= m, n <= 12
    • board[i][j] is a lowercase English letter.
    • 1 <= words.length <= 3 ∗ 1 0 4 3 * 10^4 3104
    • 1 <= words[i].length <= 10
    • words[i] 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:
    /**
     * 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
  • 相关阅读:
    操作系统拾遗(奇数篇)
    用lombok插件,驼峰属性第一个是一个字母的,属性没有接收到值,使用@JsonProperty解决(工作遇到的坑)
    Python 实现自动化测试 dubbo 协议接口
    2022腾讯云年终双十一配置表汇总-云服务器CVM+轻量应用服务器
    VMware使用Window、WinXP等虚拟机上不了网的解决办法(管用)
    List,Map多层循环嵌套Demo及其理解
    MySQL笔记-07 常用函数
    查看C语言文件依赖关系(用-Wp,MD参数生成.d文件)
    C++的类与对象(三):构造函数、析构函数、对象的销毁顺序
    java计算机毕业设计基于安卓Android的助农商城APP-农业信息app-计算机毕业设计
  • 原文地址:https://blog.csdn.net/navicheung/article/details/133631386