单词的压缩编码java_LeetCode820.单词的压缩编码

深入浅出node. js+node学习指南书

208.6元

(需用券)

去购买 >

929786ecccef1bc1705862f3c6fd03b5.png

我的LeetCode:https://leetcode-cn.com/u/ituring/

我的LeetCode刷题源码[GitHub]:https://github.com/izhoujie/Algorithmcii

LeetCode 820. 单词的压缩编码

题目

给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。

例如,如果这个列表是 ["time", "me", "bell"],我们就可以将其表示为 S = "time#bell#" 和 indexes = [0, 2, 5]。

对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 "#" 结束,来恢复我们之前的单词列表。

那么成功对给定单词列表进行编码的最小字符串长度是多少呢?

示例:

输入: words = ["time", "me", "bell"]

输出: 10

说明: S = "time#bell#" , indexes = [0, 2, 5] 。

提示:

1 <= words.length <= 2000

1 <= words[i].length <= 7

每个单词都是小写字母 。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/short-encoding-of-words

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

分析完题目后发现,只要有相同后缀的都可以合并只统计较长的那个字符串长度并加1(#占一个长度)

问题在于如何去判断一堆字符串是否某几个有相同后缀,比较容易想到的是endWiths()和indexOf()两个方法,原理类似,但效率太低;

endwiths()和indexOf()慢在每次每个字符都需要一次全扫描,如果能一次扫描并记录效率将成倍提升,所以更高效的是构造并记录索引,即Trie(单词查找树/字典树);

思路1-使用endwitchs()或indexOf()判断是否有相同后缀

步骤:

对所有单词按长度降序排序;

一次遍历,将单词追加到StringBuilder并每次额外追加一个#,追加的前提条件是StringBuilder中indexOf(当前单词+#)结果为-1;

返回StringBuilder的长度即为结果;

思路2-构造Trie,需要构造节点

步骤:

对所有单词按长度降序排序,定义节点Node类,持有一个26长度的Node数组,26个数对应a到z;

依次取每个单词,倒序遍历每个字符,并构造字典树,若需要新建节点说明是新单词,构造完统计其长度加1,若无需构造节点说明该单词是某个单词的后缀,不统计其长度;

累加统计的新单词长度即结果;

Trie树实际上是一颗每层都有26个子节点的多叉树,其实跟二叉树是一样的逻辑,只不过层节点变多了

算法源码示例

package leetcode;

import java.util.Arrays;

/**

* @author ZhouJie

* @date 2020年3月28日 下午9:53:38

* @Description: 820. 单词的压缩编码

*

*/

public class LeetCode_0820 {

}

class Solution_0820 {

/**

* @author: ZhouJie

* @date: 2020年3月28日 下午9:54:12

* @param: @param words

* @param: @return

* @return: int

* @Description: 1-按长度降序排序,然后拼接,使用indexof()

*

*/

public int minimumLengthEncoding_1(String[] words) {

// 按长度降序排序

Arrays.sort(words, (s1, s2) -> s2.length() - s1.length());

StringBuilder sb = new StringBuilder();

for (String s : words) {

if (sb.indexOf(s + "#") == -1) {

sb.append(s).append("#");

}

}

return sb.length();

}

/**

* @author ZhouJie

* @date 2020年3月29日 上午1:33:22

* @Description: 辅助索引节点

*

*/

class TailNode {

TailNode[] next = new TailNode[26];

}

/**

* @author: ZhouJie

* @date: 2020年3月29日 上午1:33:24

* @param: @param words

* @param: @return

* @return: int

* @Description: 2-Tail,建立字典索引

*

*/

public int minimumLengthEncoding_2(String[] words) {

// 按长度降序排序

Arrays.sort(words, (s1, s2) -> s2.length() - s1.length());

int minLen = 0;

// 根索引

TailNode root = new TailNode();

for (String s : words) {

// 每次都从根开始搜索

TailNode currNode = root;

// 当前单词是否需要单独新建索引

boolean f = false;

for (int i = s.length() - 1; i > -1; i--) {

int index = s.charAt(i) - 'a';

// 当前字符是否已建立索引,若未建立索引则新建索引并更新布尔值

if (currNode.next[index] == null) {

f = true;

currNode.next[index] = new TailNode();

}

// 搜索下一个索引

currNode = currNode.next[index];

}

if (f) {

// 记录新建索引增加的长度

minLen += s.length() + 1;

}

}

return minLen;

}

}

java 11官方入门(第8版)教材

79.84元

包邮

(需用券)

去购买 >

f0f3f55624fb396b1764d42d6df88864.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值