I have already written a program that can find the most frequent (furthest left) and second most frequent character that is furthest to the right, but I cannot figure out how to make the second most frequent method insist on the first character that appears from the left.
Here's what I need the method to do:
secondMostFrequent("abcdbcd") = 'c'
secondMostFrequent("abbcdbcd") = 'c'
Whereas my method does this:
secondMostFrequent("abcdbcd") = 'd'
mostFrequent("abcdbcd") = 'b'
And here's the code:
public static Character mostFrequent(String s) {
String sHold = s;
Character[] arrayHold = toCharacterArray(sHold); //toCharacterArray() converts the string into an array of characters
char element = ' ';
int count = 0;
for(int i = 0; i < arrayHold.length; i++){
char tempElement = arrayHold[i];
int tempCount = 0;
for(int j = 0; j < arrayHold.length; j++){
if(arrayHold[j] == tempElement){
tempCount++;
if(tempCount > count) {
element = tempElement;
count = tempCount;
}
}
}
}
return element;
}
public static Character[] toCharacterArray(String s ) { //serves to convert a string into an array of characters
if (s == null) {
return null;
}
int len = s.length();
Character[] array = new Character[len];
for (int i = 0; i < len ; i++) {
array[i] = s.charAt(i);
}
return array;
}
public static Character secondMostFrequent(String s){
String sHold = s;
Character[] arrayHold = toCharacterArray(sHold);
char element = ' ';
char element2 = ' ';
int count = 0;
int count2 = 0;
for(int i = 0; i < arrayHold.length; i++){
char tempElement = arrayHold[i];
char tempElement2 = arrayHold[i];
int tempCount = 0;
int tempCount2 = 0;
for(int j = 0; j < arrayHold.length; j++){
if(arrayHold[j] == tempElement){
tempCount++;
if(tempCount > count) {
element = tempElement;
count = tempCount;
}
else{
element2 = tempElement2;
count2 = tempCount2;
}
}
}
}
return element2;
}
public static void main (String[]args){
System.out.println("The most common character is: " + "'" + mostFrequent("abcdbcd") + "'");
System.out.println("The second most common character is: " + "'" + secondMostFrequent("abcdbcd") + "'");
}
}
That's the solution to your task.
Time complexity: O(n)
It does two iterations over the given string:
public static Character secondMostFrequent(String source) {
Map<Character, Integer> hist = getHistogram(source);
char firstChar = 0;
char secondChar = 0;
int firstCount = 0;
int secondCount = 0;
for (int i = 0; i < source.length(); i++) {
char next = source.charAt(i);
if (firstCount == 0 || hist.get(next) > firstCount) {
secondChar = firstChar;
secondCount = firstCount;
firstChar = next;
firstCount = hist.get(next);
}
else if (next != firstChar &&
(secondCount == 0 || hist.get(next) > secondCount)) {
secondChar = next;
secondCount = hist.get(next);
}
}
return secondChar;
}
private static Map<Character, Integer> getHistogram(String source) {
Map<Character, Integer> hist = new HashMap<>();
for (int i = 0; i < source.length(); i++) {
hist.merge(source.charAt(i), 1, Integer::sum);
}
return hist;
}
output
for these calls:
System.out.println(secondMostFrequent("abcdbcd"));
System.out.println(secondMostFrequent("abbcdbcd"));
System.out.println(secondMostFrequent("abcccdeeeaaa"));
c
c
e
If you've got a function that returns the most common character, you can use it to make a function that returns the second most common character by removing the most frequent character:
public static Character secondMostFrequent(String source) {
return mostFrequent(source.replaceAll(Character.toString(mostFrequent(source)), ""));
}
Alternatively if you have a working function that returns the second most frequent character from right to left and you want it from left to right, reverse the string before calling the function.
These are admittedly "quick fixes" to get it going. But sometimes, that's all you need.
You should use PriorityQueue
to find out nth
most frequent character. Just remember every time you insert new element to the priority queue, all existed elements in the queue are sorted according to the given comparator.
public static char findMostFrequent(String str, int num) {
class Pair {
final char ch;
int count;
public Pair(char ch) {
this.ch = ch;
}
}
Map<Character, Pair> map = new HashMap<>();
for (int i = 0; i < str.length(); i++)
map.computeIfAbsent(str.charAt(i), Pair::new).count++;
final Comparator<Pair> sortByCountAsc = Comparator.comparingInt(one -> one.count);
final Comparator<Pair> sortByCharacterAsciiAsc = Comparator.comparingInt(one -> one.ch);
final Comparator<Pair> sortByMostCommonDesc = sortByCountAsc.reversed().thenComparing(sortByCharacterAsciiAsc);
Queue<Pair> queue = new PriorityQueue<>(sortByMostCommonDesc);
queue.addAll(map.values());
int i = 1;
while (!queue.isEmpty()) {
Pair pair = queue.remove();
if (i++ == num)
return pair.ch;
}
return '\0';
}
Demo:
public static void main(String[] args) {
System.out.println(findMostFrequent("abbcdbcd", 1)); // b
System.out.println(findMostFrequent("abcdbcd", 2)); // c
System.out.println(findMostFrequent("abbcdbcd", 2)); // c
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.