LeetCode 820. 单词的压缩编码 (Java版; Meidum)
题目描述
给定一个单词列表,我们将这个列表编码成一个索引字符串 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
每个单词都是小写字母 。
第一次做; 核心: 1)前缀树; 使用哈希表记录邻居, 方便知道当前节点是否有邻居, 通过isEmpty()判断; 使用数组记录邻居就不方便判断是否有邻居了
class Solution {
public int minimumLengthEncoding ( String[ ] words) {
HashSet< String> set = new HashSet < > ( Arrays. asList ( words) ) ;
Trie trie = new Trie ( ) ;
for ( String s : set) {
trie. add ( s) ;
}
return trie. getDepthSum ( ) ;
}
class Trie {
Node root;
HashSet< Node> set;
Trie ( ) {
root = new Node ( ) ;
set = new HashSet < > ( ) ;
}
void add ( String str) {
Node cur = root;
for ( int i= str. length ( ) - 1 ; i>= 0 ; i-- ) {
char ch = str. charAt ( i) ;
if ( ! cur. next. containsKey ( ch) ) {
cur. next. put ( ch, new Node ( ) ) ;
}
cur = cur. next. get ( ch) ;
}
cur. depth = str. length ( ) + 1 ;
set. add ( cur) ;
}
int getDepthSum ( ) {
int res = 0 ;
for ( Node node : set) {
if ( node. next. isEmpty ( ) ) {
res += node. depth;
}
}
return res;
}
}
class Node {
HashMap< Character, Node> next;
int depth;
Node ( ) {
next = new HashMap < > ( ) ;
}
}
}
第一次做; 核心: 1)使用set记录每个单词, 然后针对每一个单词, 考虑其子串[i,n-1], 将该子串从set中删除, i>=1, 因为这些子串都是当前单词的后缀 2) HashSet可以使用forEach, HashMap不行 3)Arrays.asList(T… a), 返回值类型是List 3)将所有单词放入set, 可以先过滤掉重复出现的单词
class Solution {
public int minimumLengthEncoding ( String[ ] words) {
Set< String> set = new HashSet ( Arrays. asList ( words) ) ;
for ( String word : words) {
for ( int i= 1 ; i< word. length ( ) ; i++ ) {
set. remove ( word. substring ( i) ) ;
}
}
int res= 0 ;
for ( String s : set) {
res += s. length ( ) + 1 ;
}
return res;
}
}
public int minimumLengthEncoding ( String[ ] words) {
Node trie = new Node ( ) ;
Set< Node> nodes = new HashSet < > ( ) ;
for ( String w : words) {
Node node = trie;
for ( int i = w. length ( ) - 1 ; i >= 0 ; i-- )
node = node. add ( w. charAt ( i) ) ;
node. depth = w. length ( ) + 1 ;
nodes. add ( node) ;
}
return nodes. stream ( ) . filter ( n - > n. leaf) . mapToInt ( n - > n. depth) . sum ( ) ;
}
class Node {
final Node[ ] next = new Node [ 26 ] ;
boolean leaf = true ;
int depth;
Node add ( char c) {
if ( next[ c - 'a' ] == null)
next[ c - 'a' ] = new Node ( ) ;
leaf = false ;
return next[ c - 'a' ] ;
}
}
class Solution {
public int minimumLengthEncoding ( String[ ] words) {
TrieNode root = new TrieNode ( ) ;
List< TrieNode> leaves = new ArrayList < TrieNode> ( ) ;
for ( String w : new HashSet < > ( Arrays. asList ( words) ) ) {
TrieNode cur = root;
for ( int i = w. length ( ) - 1 ; i >= 0 ; -- i) {
char j = w. charAt ( i) ;
if ( ! cur. next. containsKey ( j) ) cur. next. put ( j, new TrieNode ( ) ) ;
cur = cur. next. get ( j) ;
}
cur. depth = w. length ( ) + 1 ;
leaves. add ( cur) ;
}
int res = 0 ;
for ( TrieNode leaf : leaves) if ( leaf. next. isEmpty ( ) ) res += leaf. depth;
return res;
}
}
class TrieNode {
HashMap< Character, TrieNode> next = new HashMap < > ( ) ;
int depth;
}