博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Design CML-TAB
阅读量:7174 次
发布时间:2019-06-29

本文共 3884 字,大约阅读时间需要 12 分钟。

题目:

题目很简单,就是设计command line里的tab键,自由发挥。

设计功能:

(1)返回可能命令集:如果当前字符串是若干个命令字符串的最长共同前缀,返回可能的命令字符串列表;
(2)自动补全:如果当前字符串是若干命令字符串的共同前缀,但不是最长共同前缀,则将其补充到最长前缀。eg:dic{document, doctor},输入Tab("d"), 返回"doc";
(3)返回最少还需要输入多长的字符才能唯一确定一个单词。

数据结构设计:

由于需要通过前缀的操作,所以选择用Trie。事实上Trie的别称是prefix tree,所有操作prefix的问题都可以考虑使用Trie。插入和查找操作时间复杂度都是O(l),l为平均字符串长度。Trie只有一点比HashTable差,就是Trie不支持delete操作。
除了常规的属性外,这里需要在TrieNode类里加上count,用来记录当前节点下有多少个单词,在功能需求(3)里会被用来判断。

分析:

Trie这种数据结构通常都是伴随着DFS搜索的,运气好的话还会要求你Backtrack,比如这道题,这都是套路。
另外这道题很容易错,重点是要先明确功能需求。下面分条说明下:
(1)需求一规定的是返回当前节点下的所有单词,这里容易漏。比如说,在字典{god, godlike}中,遍历到节点d的时候node.isWord是true,但是后面还有"godlike"这个单词。反应在代码里就是findMatch()函数的判断语句里不要写return.找到一个单词不一定是搜索树的叶子节点,要继续搜索下去。
(2)自动补全的要求是补全到最长共同前缀,而不是补全出整个单词。所以判断条件是node.child.size() == 1, 而不是node.count == 1;
(3)与自动补全相反,计算最短输入长度是要求目标能补全出整个单词,所以要用node.count来做判断。

总之要先读清楚题,划分好各个函数的边界,然后再开始coding.

code:

import java.util.*;public class TABandTrie {    static class TrieNode{        boolean isWord;        //count: the number of words under this node        int count;        String s;        HashMap
child; public TrieNode(){ count = 0; isWord = false; child = new HashMap
(); } } static class Trie{ TrieNode root; public Trie(){ root = new TrieNode(); } public void addWord(String word){ TrieNode node = this.root; for(int i = 0; i < word.length(); i++){ char c = word.charAt(i); if(!node.child.containsKey(c)) node.child.put(c, new TrieNode()); node.count++; node = node.child.get(c); } node.isWord = true; node.s = word; } } public static void findCommon(List
result, TrieNode root, StringBuilder prefix){ //if(root.count > 1 || root.isWord){ //*****如果分叉的数量等于一,注意,这里不能用count判断,上面一行代码会WA if(root.child.size() > 1 || root.isWord){ result.add(prefix.toString()); return; } else{ for(char c : root.child.keySet()){ prefix.append(c); findCommon(result, root.child.get(c), prefix); } } } public static void findMatch(List
result, TrieNode root, StringBuilder prefix){ //******寻找到一个单词就放进list,注意,这里不能写return; if(root.isWord) result.add(prefix.toString()); for(char c : root.child.keySet()){ prefix.append(c); findMatch(result, root.child.get(c), prefix); prefix.setLength(prefix.length() - 1); } } public static void tab(List
result, TrieNode root, String s, String prefix){ if(s.length() == 0){ if(root.child.size() == 1) findCommon(result, root, new StringBuilder(prefix)); else findMatch(result, root, new StringBuilder(prefix)); return; } char c = s.charAt(0); prefix += c; tab(result, root.child.get(c), s.substring(1), prefix); } public static int shortest(TrieNode root, String s, int length){ //*******注意,这里只能用count判断,因为要求是需要返回指定的单词,而不是返回最长共 //同前缀。如果是返回最长共同前缀的话用node.child.size() == 1 if(root.count == 1 && !root.isWord || s.length() == 0) return length; char c = s.charAt(0); return shortest(root.child.get(c), s.substring(1), length + 1); } public static void main(String[] args) { String[] dictionary = {"abcefegddf","abc","ab","catb","cats","robot","catsa","abcd","cc","document", "doctor"}; // String[] dictionary = {}; Trie trie = new Trie(); for(String s : dictionary){ trie.addWord(s); } List
result = new ArrayList
(); tab(result, trie.root,"ca",""); System.out.println(result); System.out.println(shortest(trie.root,"document",0)); }}

转载地址:http://budzm.baihongyu.com/

你可能感兴趣的文章
《Learning Scrapy》(中文版)第1章 Scrapy介绍
查看>>
单点登录原理与实现
查看>>
初探Java设计模式4:JDK中的设计模式
查看>>
漫谈promise使用场景
查看>>
Design Pattern的万剑归宗 => Mediator
查看>>
Javascript中的原型继承的一些看法与见解
查看>>
HackerRank:JavaScript 是最知名的编程语言
查看>>
Linux修改本地时间
查看>>
elasticsearch字符串包含查询
查看>>
5- Flask构建弹幕微电影网站-项目分析、搭建目录及模型设计
查看>>
Mysql四种常见数据库引擎
查看>>
《Kotin 极简教程》第7章 面向对象编程(OOP)(1)
查看>>
Chrome吃内存的能力可不是说着玩的!
查看>>
IntelliJ IDEA 详细图解最常用的配置 ,适合刚刚用的新人
查看>>
[20180619]fsc表示什么.txt
查看>>
域名对SEO的影响大吗?
查看>>
7年苦心钻研自动驾驶,最终Alphabet选择削减投入
查看>>
农民伯伯的福利到了,AR技术让种地更加easy
查看>>
4年后,nuTonomy要在10城市运行无人驾驶车
查看>>
李开复预言:人工智能将在10年后让50%的人失业
查看>>