-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathLongestDictWordsFromCharacters.java
72 lines (63 loc) · 2.47 KB
/
LongestDictWordsFromCharacters.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package by.andd3dfx.string;
import org.apache.commons.lang3.ArrayUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Given an array of characters and a dictionary of words,
* find the longest words that can be obtained by characters.,
* i.e. if array is {e, o, t, s} and dictionary words are [otse, tse, eo, stoe]
* then function should return [otse, stoe].
*
* @see <a href="https://youtu.be/LQeAY_jx3SA">Video solution</a>
*/
public class LongestDictWordsFromCharacters {
public static String[] find(char[] characters, String[] words) {
List<String> result = new ArrayList<>();
Map<Character, Integer> baseFreqMap = buildFreqMap(characters);
List<String> sortedWords = Arrays.stream(words)
.sorted(Comparator.comparingInt(String::length))
.toList().reversed();
var lastLength = -1;
for (var word : sortedWords) {
if (word.length() < lastLength) {
break;
}
Map<Character, Integer> wordFreqMap = buildFreqMap(word.toCharArray());
if (couldMakeThisWordUsingBaseChars(baseFreqMap, wordFreqMap)) {
result.add(word);
lastLength = word.length();
}
}
return result.toArray(new String[0]);
}
private static boolean couldMakeThisWordUsingBaseChars(Map<Character, Integer> baseFreqMap, Map<Character, Integer> wordFreqMap) {
for (var entry : wordFreqMap.entrySet()) {
var key = entry.getKey();
if (!baseFreqMap.containsKey(key) || baseFreqMap.get(key) < entry.getValue()) {
return false;
}
}
return true;
}
private static Map<Character, Integer> buildFreqMap(char[] chars) {
return Arrays.stream(ArrayUtils.toObject(chars))
.collect(Collectors.groupingBy(
ch -> ch, Collectors.summingInt(element -> 1)
));
}
private static Map<Character, Integer> buildFreqMap_Old(char[] chars) {
Map<Character, Integer> map = new HashMap<>();
for (var ch : chars) {
if (!map.containsKey(ch)) {
map.put(ch, 0);
}
map.put(ch, map.get(ch) + 1);
}
return map;
}
}