算法-单词的添加和查找

今天遇到了一道字典树的题,这是我第一次使用字典树来解决问题,所以我觉得还是有必要记录下来。

题意:

设计一个包含下面两个操作的数据结构:addWord(word), search(word)

addWord(word)会在数据结构中添加一个单词。而search(word)则支持普
通的单词查询或是只包含.和a-z的简易正则表达式的查询。

一个 . 可以代表一个任何的字母。

样例:

addWord("bad")
addWord("dad")
addWord("mad")
search("pad")  // return false
search("bad")  // return true
search(".ad")  // return true
search("b..")  // return true

注意事项:

你可以假设所有的单词都只包含小写字母 a-z。

1.字典树

字典树又称为单词查找树,是一个树形结构,是哈希树的变种。它的优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

同时,它还有3个性质:

A.根节点不包含字符,除根节点外每一个节点都只包含一个字符;

B.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;

C.每个节点的所有子节点包含的字符都不相同。

如图所示:

2.构建字典树

从上面的介绍,我们能简单的知道,字典树每一个节点里面包含了两个东西,一个是value,也就是数据,第二个是孩子,这里是孩子们,因为一个节点可能有多个孩子,不只是有1个或者2个孩子节点。

但是这里我们还需要一个flag来判断当前这个节点是否是最终节点,也就是判断这个节点是否还有孩子。为什么要这么做呢?比如,在字典树中有一个字符串是:abcd,我们想在字典树中查找abc,我们发现abcd这个路径符合要求,因为每个字符都匹配了的,但是这样判断是错误的,所以我们得判断每个节点是否是最终节点。

(1).节点的封装

    private class TreeNode {
        //节点的值
        public char value;
        //节点的孩子们
        public TreeNode child[] = null;
        //是否是最终节点
        public boolean isEnd = false;

        public TreeNode(char value) {
            this.value = value;
            child = new TreeNode[26];
        }
    }

(2).向字典树中添加字符

    public void addWord(String word) {
        TreeNode node = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            if (node.child[c - ‘a‘] == null) {
                node.child[c - ‘a‘] = new TreeNode(c);
            }
            node = node.child[c - ‘a‘];
        }
        //该节点最为最终节点
        node.isEnd = true;
    }

3.在字典树中查找单词

在普通的查找中(查找的单词不含通配符,全部是字符),自己循环查找就是,但是在这里比较特殊,查找的单词可能还有通配符,那么就不能使用普通的查找了,这里我使用的回溯法来查找的,使用回溯法将符合要求的字符串添加到一个List集合中,然后在判断一下,在这个List集合是否有我们想要的字符串。

 1 public class WordDictionary {
 2
 3     private TreeNode root = null;
 4     private List<String> list = null;
 5
 6     public WordDictionary() {
 7         root = new TreeNode(‘ ‘);
 8         list = new ArrayList<>();
 9     }
10
11     private class TreeNode {
12         //节点的值
13         public char value;
14         //节点的孩子们
15         public TreeNode child[] = null;
16         //是否是最终节点
17         public boolean isEnd = false;
18
19         public TreeNode(char value) {
20             this.value = value;
21             child = new TreeNode[26];
22         }
23     }
24
25     public void addWord(String word) {
26         TreeNode node = root;
27         for (int i = 0; i < word.length(); i++) {
28             char c = word.charAt(i);
29             if (node.child[c - ‘a‘] == null) {
30                 node.child[c - ‘a‘] = new TreeNode(c);
31             }
32             node = node.child[c - ‘a‘];
33         }
34         //该节点最为最终节点
35         node.isEnd = true;
36     }
37
38     public boolean search(String word) {
39         TreeNode node = root;
40         list.clear();
41         char cs[] = new char[word.length()];
42         Arrays.fill(cs, ‘ ‘);
43         backTrack(word, 0, node, cs);
44         //判断是否含有word字符串
45         return list.contains(word);
46     }
47
48     private void backTrack(String word, int i, TreeNode node, char cs[]) {
49         //当i < word.length() 继续搜索下去
50         if (i < word.length()) {
51             char c = word.charAt(i);
52             if (c != ‘.‘) {
53                 if (node.child[c - ‘a‘] != null) {
54                     cs[i] = c;
55                     backTrack(word, i + 1, node.child[c - ‘a‘], cs);
56                 }
57             } else {
58                 for (int j = 0; j < 26; j++) {
59                     if (node.child[j] != null) {
60                         cs[i] = ‘.‘;
61                         backTrack(word, i + 1, node.child[j], cs);
62                     }
63                 }
64             }
65         } else {
66             //node不为最终节点,所以不符合要求
67             if(!node.isEnd){
68                 return;
69             }
70             StringBuilder stringBuilder = new StringBuilder();
71             for (int j = 0; j < word.length(); j++) {
72                 stringBuilder.append(cs[j]);
73             }
74             list.add(stringBuilder.toString());
75         }
76
77     }
78 }
时间: 2024-08-04 14:27:44

算法-单词的添加和查找的相关文章

算法——蛮力法之顺序查找和蛮力字符串匹配

接着昨天的选择排序和冒泡排序之后,今天来实现一下顺序查找和蛮力字符串匹配两个算法. 顺序查找就是将给定的查找键和列表周玲的每个元素进行比较,直到找到一个匹配成功的元素返回该元素下标,查找成功,或者查找整个列表二没有匹配元素,查找失败.这里记录一下限位器版顺序查找方法.限位器就是指将查找键添加到列表最后,这样在查找的过程中,不用再每次都判断是否到达列表尾部来判断查找是否失败,而是在查找结束后,判断匹配元素下标是否小于n(假设列表有n个元素)来判断查找是否成功.下面是限位器版顺序查找算法: 限位器版

浅谈算法和数据结构: 九 平衡查找树之红黑树

原文:浅谈算法和数据结构: 九 平衡查找树之红黑树 前面一篇文章介绍了2-3查找树,可以看到,2-3查找树能保证在插入元素之后能保持树的平衡状态,最坏情况下即所有的子节点都是2-node,树的高度为lgN,从而保证了最坏情况下的时间复杂度.但是2-3树实现起来比较复杂,本文介绍一种简单实现2-3树的数据结构,即红黑树(Red-Black Tree) 定义 红黑树的主要是像是对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息.红黑树中将节点之间的链接分为两种不同类型,

一天一道算法题---6.26---二分查找

感谢微信平台---一天一道算法题----每天多一点进步-- 好累啊  现在在用win7自带的输入法 打起来真麻烦 快点把这2天的搞完就重装了 还是直接来源于----〉 待字闺中 分析 给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 没有重复元素的情况 一些同学在遇到这个题目的时候,往往会觉得比较简单.

我的软考之路(七)——数据结构与算法(5)之查找

上篇博文我重点介绍了八大内部排序,这篇博文(数据结构与算法的最后一课)重点介绍查找,我们依旧沿用上篇博文的风格,先简单介绍,再以例子重点讲解. 下面我们开始今天的旅行,首先祝你旅行愉快,呵呵. 静态查找 若查找目的是为了查询某个特定的数据是否在表中或检索某个特定数据的各种属性,则此类查找表为静态查找表. 1.顺序查找 基本原理:从表一端开始逐个和关键字进行比较,若找到一个记录和给定值相等,则查找成功,反之失败.再简单点就是,一个一个的比大小,看看是否相等. 例子: 顺序查找更适合于顺序存储结构和

关于eclipse添加自动查找文件以及svn的插件

1.添加自动查找当前文件位置的插件(如下图) 在百度搜索下载 OpenExplorer_1.5.0.v201108051313.jar,下载之后放入eclipse下面的plugin文件夹下面既可以 2.svn插件 同样的在网上下载好svn插件文件,进行解压,  然后就eclipse文件夹下dropins里面关于svn的插件全部删除  然后将下载后的插件包解压放入文件,重启eclipse即可, 当然可能会遇到错误,由于文件夹多一级的原因,此处参考 如下 http://blog.csdn.net/t

#查找算法#【1】简单查找:顺序、折半查找

•顺序查找 从线性表的一端开始,依次将每个记录的关键字与给定值进行比较,若某个记录的关键字等于给定值,表示查找成功,返回记录序号:若将线性表中所有记录都比较完,仍未找到关键字与给定值相等的记录,则表示查找失败,返回一个失败值. •折半查找 又称为二分查找.这种查找方法要求查找表的数据是线性结构保存,并且还要求查找表中的数据是按关键字由小到大有序排列. 顺序查找比较简单,依次用数组中的每个元素和要查找的元素进行对比即可.不再贴代码说明 折半查找是一种递归过程,每折半一次,可使查找范围缩小一半,当查

二叉树,添加,查找

public class Tree { TreeNode last = null; TreeNode root = null; public Tree(int value){ root = createNode(value); } //结构 static class TreeNode{ int data; TreeNode left; TreeNode right; } //查找结点 public boolean searchTreeNode(int key,TreeNode tree){ if

浅谈算法和数据结构: 十 平衡查找树之B树

转载自 http://www.cnblogs.com/yangecnu/p/3632027.html 浅谈算法和数据结构: 十 平衡查找树之B树 前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据.对其进行排序并允许以O(log n)的时间复杂度运行进行查找.顺序读取.插入和删除的数据结构.B树,概括来说是一个节点可以拥

十大基础实用算法之归并排序和二分查找

归并排序 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 算法步骤: 1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置 3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 4. 重复步骤3直到某一指针达到序列尾 5. 将另一序列剩下的所有元素直接复制到合并序列尾 用分治策略解决问题分为三步:分解