字符串搜索dfs题79_208_212

2023-11-02

79. Word Search

给一个二维字符数组和一个字符串,判断是否存在一条路径使得路径字符等于所给字符串。

board =
[ [‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]]
Given word = “ABCCED”, return true.
Given word = “SEE”, return true.
Given word = “ABCB”, return false.

从数组中每个字符处开始进行递归,看是否存在一个合法路径:

public boolean exist(char[][] board, String word) {
    if (board.length == 0) return false;
    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            if (help(board, i, j, word, 0)) {
                return true;
            }
        }
    }
    return false;
}

public boolean help(char[][] board, int i, int j, String word, int index) {
    if (word.length() == index)
        return true;

    if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(index)) {
        return false;
    }

    char record = board[i][j];
    board[i][j] = '#';
    if (help(board, i-1, j, word, index+1) || help(board, i+1, j, word, index+1)
    || help(board, i, j-1, word, index+1) || help(board, i, j+1, word, index+1))
        return true;

    board[i][j] = record;
    return false;
}

208. Implement Trie (Prefix Tree)

实现一个Trie数据结构,具有insert, search, and startsWith方法,方法具体作用如例子所示。

Trie trie = new Trie();
trie.insert(“apple”);
trie.search(“apple”); // returns true
trie.search(“app”); // returns false
trie.startsWith(“app”); // returns true
trie.insert(“app”);
trie.search(“app”); // returns true

主要用嵌套数组实现,不懂为什么我代码逻辑和别人的一摸一样,但是速度却慢了一倍:

class Trie {
    /** Initialize your data structure here. */
    public Trie() {
        // root = new TrieNode();
    }

    public class TrieNode {
        TrieNode[] children = new TrieNode[26];
        boolean is_word = false;
    }

    TrieNode root = new TrieNode();
    /** Inserts a word into the trie. */
    public void insert(String word) {
        TrieNode nt = root;
        for (int i = 0; i < word.length(); i++) {
            int index = word.charAt(i) - 'a';
            if (nt.children[index] == null) {
                nt.children[index] = new TrieNode();
            }
            nt = nt.children[index];
        }
        nt.is_word = true;
    }

    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        TrieNode nt = root;
        for (int i = 0; i < word.length(); i++) {
            int index = word.charAt(i) - 'a';
            if (nt.children[index] == null)
                return false;

            nt = nt.children[index];
        }
        return nt.is_word;
    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        TrieNode nt = root;
        for (int i = 0; i < prefix.length(); i++) {
            int index = prefix.charAt(i) - 'a';
            if (nt.children[index] == null)
                return false;
            nt = nt.children[index];
        }
        return true;
    }
}

212. Word Search II

给一个二维字符数组和一个字符串列表,将所有在数组路径上的字符串返回。

79题的进阶版,79是存在问题,本题是查找,需要遍历所有路径,不过可以通过判断字符串前缀进行剪枝,所以要利用Trie数据结构,非常有效。

不过直接使用Trie的话速度无法达到极限,可以结合本题改造一下:

public List<String> findWords(char[][] board, String[] words) {
    TrieNode trie = new TrieNode();
    for (String s : words)
        trie.insert(s, trie);

    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            help(board, i, j, new StringBuffer(""), trie);
        }
    }

    return res;
}

List<String> res = new ArrayList<>();
public void help(char[][] board, int i, int j, StringBuffer str, TrieNode trie) {
    char record = board[i][j];
    //如果该字符遍历过,或者不在任意一个字符串的前缀中时直接返回
    if (record == '#' || trie.children[record - 'a'] == null)
        return;

	//对二维数组递归的同时也对Trie递归,这样不用单独声明一个字符串来判断当前路径来
    trie = trie.children[record - 'a'];
    if (trie.word != null) {
        res.add(trie.word);
        trie.word = null;
    }

    board[i][j] = '#';
    if (i > 0) help(board, i-1, j, str, trie);
    if (i < board.length-1) help(board, i+1, j, str, trie);
    if (j > 0) help(board, i, j-1, str, trie);
    if (j < board[0].length) help(board, i, j+1, str, trie);
    board[i][j] = record;
}

class TrieNode {
    TrieNode[] children = new TrieNode[26];
    String word;

    public void insert(String word, TrieNode root) {
        TrieNode nt = root;
        for (int i = 0; i < word.length(); i++) {
            int index = word.charAt(i) - 'a';
            if (nt.children[index] == null) {
                nt.children[index] = new TrieNode();
            }
            nt = nt.children[index];
        }
        //字符串储存完直接将其记录而不是判断是否是一个字符串
        nt.word = word;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字符串搜索dfs题79_208_212 的相关文章

  • 基于线性预测的语音编码原理解析

    早期的音频系统都是基于声音的模拟信号实现的 在声音的录制 编辑和播放过程中很容易引入各种噪声 从而导致信号的失真 随着信息技术的发展 数字信号处理技术在越来越多领域得到了应用 数字信号更是具备了易于存储和远距离传输 没有累积失真 抗干扰能力

随机推荐