这是悦乐书的第303次更新,第322篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第171题(顺位题号是720)。给出表示英语词典的字符串单词数组,找到单词中长度最长的单词,此单词可以通过数组中的其他单词一次次构建一个字符而得来。如果有多个可能的答案,则返回字典顺序最小的最长单词。如果没有答案,则返回空字符串。例如:

输入:words = [“w”,“wo”,“wor”,“worl”,“world”]

输出:“world”

说明:“world”这个词可以通过“w”,“wo”,“wor”和“worl”一次构建一个字符。



输入:words = [“a”,“banana”,“app”,“appl”,“ap”,“apply”,“apple”]

输出:“apple”

说明:“apply”和“apple”都可以从字典中的其他单词构建。但是,“apple”在词典上比“apply”更小(靠前)。



注意:

  • 输入中的所有字符串仅包含小写字母。

  • 单词的长度将在[1,1000]范围内。

  • 单词[i]的长度将在[1,30]的范围内。

本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

02 第一种解法

在解题前,需要先注意题目中的几个信息,一是满足题目条件的结果字符串,是有一个个字符累加起来的,在我的一次提交中,有{"ew","ewq","ewqz"}这三个字符串,我的算法算出来是第三个"ewqz",但其实它还缺少一个"e",是不符合题目要求的。二是如果满足题目条件的字符串有两个或者多个,需要去比较谁更小,也就是按照字母顺序由小到大排列的,谁更靠前谁更小。

思路是先将字符串放进HashMap中,key为每一个单词,value为单词的长度。循环单词数组,比较谁的长度更小,此处分为两种情况处理:一是大于已有最大长度,二是等于已有最大长度,另外,无论遇到那种情况,都需要去判断当前字符是否是由单个单词一次次累加变成的,对此单独写了一个方法判断当前单词是否符合题目要求的方法isExists。针对第二种情况,需要去比较两个单词的大小,也写了一个额外的方法isMin来判断,如果满足,就将结果字符串更新,最长长度保持不变。

Map<String, Integer> map = new HashMap<String, Integer>();
public String longestWord(String[] words) {
for (String str : words) {
map.put(str, str.length());
}
int len = Integer.MIN_VALUE;
String result = "";
for (String str : words) {
if (isExists(str) && str.length() > len) {
result = str;
len = str.length();
} else if (isExists(str) && str.length() == len) {
if (result != "") {
if (isMin(str, result)) {
result = str;
}
}
}
}
return result;
} /**
* 判断str是否小于str2
* @param str 新遇到的等长字符串
* @param str2 上一次的最长字符串
* @return true:str中的字符小于str2
*/
public boolean isMin(String str, String str2){
for (int i=0; i<str.length(); i++) {
if (str.charAt(i) < str2.charAt(i)) {
return true;
} else if (str.charAt(i) == str2.charAt(i)) {
continue;
} else {
return false;
}
}
return false;
} /**
* 判断当前字符串在数组中是否是一个个字符慢慢累加起来的
* @param str
* @return
*/
public boolean isExists(String str) {
String ss = "";
for (char ch : str.toCharArray()) {
ss += ch;
if (!map.containsKey(ss)) {
return false;
}
}
return true;
}

03 第二种解法

在第一种解法中,并没有用到HashMap中的value值,因此可以使用HashSet来存储数组中的单词。其次,也可以通过数组排序的方式,省去后续循环中判断最长长度相等的情况,也省去了比较两个字符串谁更小的判断,更加的简洁。

Set<String> set = new HashSet<String>();
public String longestWord2(String[] words) {
Arrays.sort(words);
for (String word : words) {
set.add(word);
}
int len = Integer.MIN_VALUE;
String result = "";
for (String str : words) {
if (isExists2(str) && str.length() > len) {
result = str;
len = str.length();
}
}
return result;
} public boolean isExists2(String str) {
String ss = "";
for (char ch : str.toCharArray()) {
ss += ch;
if (!set.contains(ss)) {
return false;
}
}
return true;
}

04 第三种解法

也可以只使用一个循环来解决。依旧是数组排序,使用HashSet存储数组中的单词,但是存入HashSet的操作是在循环中进行的,如果当前单词的长度等于1或者其本身的子串也存在于HashSet中,才存入HashSet,此步骤就相当于第一种解法和第二种解法中判断当前单词是否符合题目要求,由一个字符一次次累加得来的。如果当前字符的长度大于结果单词的长度,就进行赋值更新操作。

public String longestWord3(String[] words) {
Set<String> set = new HashSet<String>();
Arrays.sort(words);
String result = "";
for (String word : words) {
if (word.length() == 1 || set.contains(word.substring(0, word.length()-1))) {
if (word.length() > result.length()) {
result = word;
}
set.add(word);
}
}
return result;
}

05 第四种解法

我们也可以不借助排序来实现,其实也是对第二种解法的优化。依旧是使用HashSet,也借助了一个辅助方法isExists2来判断当前单词是否符合题目要求,但不同的是,在循环中,此判断只在当前单词长度大于结果单词的长度,或者两者长度相等且新单词小于结果单词这两种情况下进行,而不像第二种解法那样,每次都去先判断当前单词是否符合题目要求,再去比较长度。其中,比较两个单词的大小借助了字符串自带的compareTo方法。

Set<String> set = new HashSet<String>();
public String longestWord4(String[] words) {
for (String word : words) {
set.add(word);
}
String result = "";
for (String word : words) {
if (word.length() > result.length() || (word.length() == result.length() && word.compareTo(result) < 0)) {
if (isExists2(word)) {
result = word;
}
}
}
return result;
} public boolean isExists2(String str) {
String ss = "";
for (char ch : str.toCharArray()) {
ss += ch;
if (!set.contains(ss)) {
return false;
}
}
return true;
}

06 小结

算法专题目前已日更超过五个月,算法题文章171+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

LeetCode算法题-Longest Word in Dictionary(Java实现)的更多相关文章

  1. LeetCode算法题-Longest Univalue Path(Java实现)

    这是悦乐书的第290次更新,第308篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第158题(顺位题号是687).给定二叉树,找到路径中每个节点具有相同值的最长路径的长度 ...

  2. LeetCode算法题-Longest Harmonious Subsequence(Java实现)

    这是悦乐书的第270次更新,第284篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第136题(顺位题号是594).我们定义一个和谐数组是一个数组,其最大值和最小值之间的差 ...

  3. LeetCode算法题-Longest Continuous Increasing Subsequence(Java实现)

    这是悦乐书的第286次更新,第303篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第154题(顺位题号是674).给定未排序的整数数组,找到最长连续增加子序列的长度.例如 ...

  4. LeetCode算法题-Longest Uncommon Subsequence I(Java实现)

    这是悦乐书的第252次更新,第265篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第119题(顺位题号是521).给定一组两个字符串,您需要找到这组两个字符串中最长的不同 ...

  5. LeetCode算法题-Subdomain Visit Count(Java实现)

    这是悦乐书的第320次更新,第341篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第189题(顺位题号是811).像"discuss.leetcode.com& ...

  6. LeetCode算法题-Letter Case Permutation(Java实现)

    这是悦乐书的第315次更新,第336篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第184题(顺位题号是784).给定一个字符串S,将每个字母单独转换为小写或大写以创建另 ...

  7. LeetCode算法题-Jewels and Stones(Java实现)

    这是悦乐书的第313次更新,第334篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第182题(顺位题号是771).字符串J代表珠宝,S代表你拥有的石头.S中的每个字符都是 ...

  8. LeetCode算法题-Reach a Number(Java实现)

    这是悦乐书的第310次更新,第331篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第179题(顺位题号是754).你站在无限数字线的0号位置.在目的地有个target.在 ...

  9. LeetCode算法题-Self Dividing Numbers(Java实现)

    这是悦乐书的第305次更新,第324篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第173题(顺位题号是728).自分割数是一个可被其包含的每个数字整除的数字.例如,12 ...

随机推荐

  1. 【原】无脑操作:ElasticSearch学习笔记(01)

    开篇来自于经典的“保安的哲学三问”(你是谁,在哪儿,要干嘛) 问题一.ElasticSearch是什么?有什么用处? 答:截至2018年12月28日,从ElasticSearch官网(https:// ...

  2. June 29th. 2018, Week 26th. Friday

    Real love is always worth waiting for. 真爱永远值得等待. From Westworld. Real love is rare, but it does exis ...

  3. kafka 幂等生产者及事务(kafka0.11之后版本新特性)

    1. 幂等性设计1.1 引入目的生产者重复生产消息.生产者进行retry会产生重试时,会重复产生消息.有了幂等性之后,在进行retry重试时,只会生成一个消息. 1.2 幂等性实现1.2.1 PID ...

  4. ASP.NET Aries 高级开发教程:Excel导入之代码编写(番外篇)

    前言: 以许框架提供的导入配置功能,已经能解决95%以上的导入情况,但有些情况总归还是得代码来解决. 本篇介绍与导入相关的代码. 1.前端追加导入时Post的参数: var grid = new AR ...

  5. ReactiveSwift源码解析(三) Signal代码的基本实现

    上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...

  6. hadoop rpc协议客户端与服务端的交互流程

    尽管这里是hadoop的rpc服务,但是hadoop还是做到了一次连接仅有一次认证.具体的流程待我慢慢道来. 客户端:这里我们假设ConnectionId对应的Connection并不存在.在调用ge ...

  7. Linux知识要点大全(第三章)

    第三章  Linux基本操作 *主要内容 1:认识root用户 2:Linux下命令的写法 3:Linux关机和重启 4:忘记root密码的处理方法 5.  Linux下的目录结构 6.  查看信息 ...

  8. 区块链技术现状&前景

    炒作周期 Gartner 在 2017 年发布的新兴技术炒作曲线,这张图是去年 8 月发布的,当时估计它们也没料到随后能有那么火,当时区块链在这个位置,其实是已经过了炒作的巅峰期,正在往低谷走的这个阶 ...

  9. 两个案例轻松理解MyBatis中的TypeHandler!

    在做开发时,我们经常会遇到这样一些问题,比如我有一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,怎么实现?再比如我有一个User类,User类中有一个属性叫做 ...

  10. dubbo不完全指南

    Dubbo架构 节点角色说明 节点 角色说明 Provider 暴露服务的服务提供方 Consumer 调用远程服务的服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的 ...