我想要实现的是,当有一个给定的单词时,我需要找出该字符串中第二个最频繁的字符。
除此之外,还有一些我想要实现的选项。例如,
-
如果是字符串," abababd",则有四个',四b '一个d '',那么在本例中,我需要打印出'd"。
-
如果字符串为" abababdc",则有四个',四b ',一个d ''和c '',我需要打印出'dc'
public class MemorizeWorld { public static void main(String[] args) { Solution solution = new Solution(); String a = "ababababd"; solution.solution(a); } } class Solution { public void solution(String a) { int[] array = new int[26]; char[] char_array = a.toCharArray(); for(int i = 0; i < char_array.length; i++) { int index = char_array[i] - 'a'; array[index]++; } int max = 0; for(int i = 0; i < array.length; i++) { if(array[i] > max) { max = array[i]; } } } }
这就是我到目前为止所做的,我一直在寻找解决方案。我知道如何通过关注geeksforgeeks的帖子来获得第二个最常见的字符,但我不知道我应该如何将上述两个选项应用于此。有人能帮我解决这个问题吗?
找到第二个最大值,就像找到最大值一样。
int max2 = 0;
for(int i = 0; i < array.length; i++) {
if(array[i] > max2 && array[i] < max) {
max2 = array[i];
}
}
然后获取频率与第二个最大值相同的结果字符串。
String result = "";
for(int i = 0; i < array.length; i++) {
if(array[i] == max2) {
result += (i + 'a');
}
}
流API可用于此解决方案:
- 使用
Collectors.groupingBy
+Collectors.summingInt / Collectors.counting()
创建频率映射 - "invert"使用
Collectors.toMap
或Collectors.groupingBy
+Collectors.joining
对频率相同的字符进行合并;使用TreeMap
和反向键比较器 - 跳过第一个引用最大频率的值,并返回下一个值:
public static String get2ndMostFrequent(String str) {
if (null == str || str.length() < 2) {
return null;
}
return Arrays.stream(str.split("")) // Stream<String> chars
.collect(Collectors.groupingBy(
s -> s, LinkedHashMap::new, Collectors.summingInt(s -> 1)
))
.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getValue,
Map.Entry::getKey,
(s1, s2) -> s1 + s2,
() -> new TreeMap<Integer, String>(Comparator.reverseOrder())
))
.values()
.stream()
.skip(1)
.findFirst()
.orElse(null);
}
测试:
for (String s : Arrays.asList("ababababd", "ababdababc", "dabbcacd", "acbdagh")) {
System.out.println(s + " -> " + get2ndMostFrequent(s));
}
输出ababababd -> d
ababdababc -> dc
dabbcacd -> null // no 2nd frequency
acbdagh -> cbdgh