Welcome to Subscribe On Youtube

212. Word Search II

Description

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 * 104
  • 1 <= words[i].length <= 10
  • words[i] consists of lowercase English letters.
  • All the strings of words are unique.

Solutions

The solution to problem 79. Word Search can be reused here. Just search for each word in words and check whether it exists, and add the words that exist to the result list.

There also exist other solutions like Trie + DFS.

  • class Trie {
        Trie[] children = new Trie[26];
        int ref = -1;
    
        public void insert(String w, int ref) {
            Trie node = this;
            for (int i = 0; i < w.length(); ++i) {
                int j = w.charAt(i) - 'a';
                if (node.children[j] == null) {
                    node.children[j] = new Trie();
                }
                node = node.children[j];
            }
            node.ref = ref;
        }
    }
    
    class Solution {
        private char[][] board;
        private String[] words;
        private List<String> ans = new ArrayList<>();
    
        public List<String> findWords(char[][] board, String[] words) {
            this.board = board;
            this.words = words;
            Trie tree = new Trie();
            for (int i = 0; i < words.length; ++i) {
                tree.insert(words[i], i);
            }
            int m = board.length, n = board[0].length;
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    dfs(tree, i, j);
                }
            }
            return ans;
        }
    
        private void dfs(Trie node, int i, int j) {
            int idx = board[i][j] - 'a';
            if (node.children[idx] == null) {
                return;
            }
            node = node.children[idx];
            if (node.ref != -1) {
                ans.add(words[node.ref]);
                node.ref = -1;
            }
            char c = board[i][j];
            board[i][j] = '#';
            int[] dirs = {-1, 0, 1, 0, -1};
            for (int k = 0; k < 4; ++k) {
                int x = i + dirs[k], y = j + dirs[k + 1];
                if (x >= 0 && x < board.length && y >= 0 && y < board[0].length && board[x][y] != '#') {
                    dfs(node, x, y);
                }
            }
            board[i][j] = c;
        }
    }
    
  • class Trie {
    public:
        vector<Trie*> children;
        int ref;
    
        Trie()
            : children(26, nullptr)
            , ref(-1) {}
    
        void insert(const string& w, int ref) {
            Trie* node = this;
            for (char c : w) {
                c -= 'a';
                if (!node->children[c]) {
                    node->children[c] = new Trie();
                }
                node = node->children[c];
            }
            node->ref = ref;
        }
    };
    
    class Solution {
    public:
        vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
            Trie* tree = new Trie();
            for (int i = 0; i < words.size(); ++i) {
                tree->insert(words[i], i);
            }
            vector<string> ans;
            int m = board.size(), n = board[0].size();
    
            function<void(Trie*, int, int)> dfs = [&](Trie* node, int i, int j) {
                int idx = board[i][j] - 'a';
                if (!node->children[idx]) {
                    return;
                }
                node = node->children[idx];
                if (node->ref != -1) {
                    ans.emplace_back(words[node->ref]);
                    node->ref = -1;
                }
                int dirs[5] = {-1, 0, 1, 0, -1};
                char c = board[i][j];
                board[i][j] = '#';
                for (int k = 0; k < 4; ++k) {
                    int x = i + dirs[k], y = j + dirs[k + 1];
                    if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#') {
                        dfs(node, x, y);
                    }
                }
                board[i][j] = c;
            };
    
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    dfs(tree, i, j);
                }
            }
            return ans;
        }
    };
    
  • class Trie:
        def __init__(self):
            self.children = [None] * 26
            self.w = ''
            # minor ajust, not a boolean is_end, but the whole word
            # so it's easier for dfs to save the word
    
        def insert(self, w):
            node = self
            for c in w:
                idx = ord(c) - ord('a')
                if node.children[idx] is None:
                    node.children[idx] = Trie()
                node = node.children[idx]
            node.w = w
    
    
    class Solution:
        def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
            def dfs(node, i, j):
                idx = ord(board[i][j]) - ord('a')
                if node.children[idx] is None:
                    return
                node = node.children[idx]
                if node.w:
                    ans.add(node.w)
                c = board[i][j]
                board[i][j] = '0' # 0 for visited already
                for a, b in [[0, -1], [0, 1], [1, 0], [-1, 0]]:
                    x, y = i + a, j + b
                    if 0 <= x < m and 0 <= y < n and board[x][y] != '0':
                        dfs(node, x, y)
                board[i][y] = c
    
            trie = Trie()
            for w in words:
                trie.insert(w)
            ans = set()
            m, n = len(board), len(board[0])
            for i in range(m):
                for j in range(n):
                    dfs(trie, i, j)
            return list(ans)
    
    
    ################
    
    
    class Trie:
        def __init__(self):
            self.children: List[Trie | None] = [None] * 26
            self.ref: int = -1
    
        def insert(self, w: str, ref: int):
            node = self
            for c in w:
                idx = ord(c) - ord('a')
                if node.children[idx] is None:
                    node.children[idx] = Trie()
                node = node.children[idx]
            node.ref = ref
    
    
    class Solution:
        def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
            def dfs(node: Trie, i: int, j: int):
                idx = ord(board[i][j]) - ord('a')
                if node.children[idx] is None:
                    return
                node = node.children[idx]
                if node.ref >= 0:
                    ans.append(words[node.ref])
                    node.ref = -1
                c = board[i][j]
                board[i][j] = '#'
                for a, b in pairwise((-1, 0, 1, 0, -1)):
                    x, y = i + a, j + b
                    if 0 <= x < m and 0 <= y < n and board[x][y] != '#':
                        dfs(node, x, y)
                board[i][j] = c
    
            tree = Trie()
            for i, w in enumerate(words):
                tree.insert(w, i)
            m, n = len(board), len(board[0])
            ans = []
            for i in range(m):
                for j in range(n):
                    dfs(tree, i, j)
            return ans
    
    
  • type Trie struct {
    	children [26]*Trie
    	ref      int
    }
    
    func newTrie() *Trie {
    	return &Trie{ref: -1}
    }
    func (this *Trie) insert(w string, ref int) {
    	node := this
    	for _, c := range w {
    		c -= 'a'
    		if node.children[c] == nil {
    			node.children[c] = newTrie()
    		}
    		node = node.children[c]
    	}
    	node.ref = ref
    }
    
    func findWords(board [][]byte, words []string) (ans []string) {
    	trie := newTrie()
    	for i, w := range words {
    		trie.insert(w, i)
    	}
    	m, n := len(board), len(board[0])
    	var dfs func(*Trie, int, int)
    	dfs = func(node *Trie, i, j int) {
    		idx := board[i][j] - 'a'
    		if node.children[idx] == nil {
    			return
    		}
    		node = node.children[idx]
    		if node.ref != -1 {
    			ans = append(ans, words[node.ref])
    			node.ref = -1
    		}
    		c := board[i][j]
    		board[i][j] = '#'
    		dirs := [5]int{-1, 0, 1, 0, -1}
    		for k := 0; k < 4; k++ {
    			x, y := i+dirs[k], j+dirs[k+1]
    			if x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#' {
    				dfs(node, x, y)
    			}
    		}
    		board[i][j] = c
    	}
    	for i := 0; i < m; i++ {
    		for j := 0; j < n; j++ {
    			dfs(trie, i, j)
    		}
    	}
    	return
    }
    
  • class Trie {
        children: Trie[];
        ref: number;
    
        constructor() {
            this.children = new Array(26);
            this.ref = -1;
        }
    
        insert(w: string, ref: number): void {
            let node: Trie = this;
            for (let i = 0; i < w.length; i++) {
                const c = w.charCodeAt(i) - 97;
                if (node.children[c] == null) {
                    node.children[c] = new Trie();
                }
                node = node.children[c];
            }
            node.ref = ref;
        }
    }
    
    function findWords(board: string[][], words: string[]): string[] {
        const tree = new Trie();
        for (let i = 0; i < words.length; ++i) {
            tree.insert(words[i], i);
        }
        const m = board.length;
        const n = board[0].length;
        const ans: string[] = [];
        const dirs: number[] = [-1, 0, 1, 0, -1];
        const dfs = (node: Trie, i: number, j: number) => {
            const idx = board[i][j].charCodeAt(0) - 97;
            if (node.children[idx] == null) {
                return;
            }
            node = node.children[idx];
            if (node.ref != -1) {
                ans.push(words[node.ref]);
                node.ref = -1;
            }
            const c = board[i][j];
            board[i][j] = '#';
            for (let k = 0; k < 4; ++k) {
                const x = i + dirs[k];
                const y = j + dirs[k + 1];
                if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '#') {
                    dfs(node, x, y);
                }
            }
            board[i][j] = c;
        };
        for (let i = 0; i < m; ++i) {
            for (let j = 0; j < n; ++j) {
                dfs(tree, i, j);
            }
        }
        return ans;
    }
    
    

All Problems

All Solutions