Нестандартная сортировка подсчётом Java
Задача выглядит следующим образом :
Необходимо найти число, которое встречается в этой последовательности наибольшее количество раз, а если таких чисел несколько, то найти минимальное из них, и после этого переместить все такие числа в конец заданной последовательности. Порядок расположения остальных чисел должен остаться без изменения.
* 1
* 2
* 3
* 2
* 3
* 1
* 2
Превращается в :
* 1
* 3
* 3
* 1
* 2
* 2
* 2
Причём данные нужно прочитать из файла и записать отсортированный массив тоже в файл Я попробовал решить её путём создания ТриМэпа, в котором ведется подсчёт повторений, затем пройти этот Мэп, чтобы определить необходимое число, которое повтовторяется в последовательности чаще всего и количество его повторений. А затем выводить массив без этого числа, добавить его только циклом в конце.
Собственно сам вопрос, как по мне получилось очень громоздко, я уверен, что есть более элегантное решение. Но не могу сам додуматься какое? Помогите, пожалуйста
static public void sortSequence(String inputName, String outputName) throws IOException {
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(inputName), "UTF-8"));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputName), "UTF-8"))) {
String line;
ArrayList<Integer> originArray = new ArrayList<>();
while ((line = bufferedReader.readLine()) != null) {
originArray.add(Integer.parseInt(line));
}
Map<Integer, Integer> countOfNumbers = new TreeMap<>();
for (Integer num : originArray) {
if (countOfNumbers.containsKey(num)) {
countOfNumbers.put(num, countOfNumbers.get(num) + 1);
} else {
countOfNumbers.put(num, 1);
}
}
Integer valueOfMax = 0;
int countOfMax = 0;
for (Map.Entry<Integer, Integer> pair : countOfNumbers.entrySet()) {
if (pair.getValue() > countOfMax) {
countOfMax = pair.getValue();
valueOfMax = pair.getKey();
}
}
for (Integer number : originArray) {
if (!number.equals(valueOfMax)) {
bufferedWriter.write(number.toString());
bufferedWriter.newLine();
bufferedWriter.flush();
} else {
continue;
}
}
while (countOfMax > 0) {
bufferedWriter.write(valueOfMax.toString());
bufferedWriter.newLine();
bufferedWriter.flush();
countOfMax--;
}
}
}
Ответы (2 шт):
Ответ такой предложу.
Первые два цикла можно объединить. Считать количество все равно придется. В третьем цикле вы не учитываете равенство countOfMax и выбор наименьшего. А по остальному я проблем не вижу.
В принципе алгоритм не отличается, просто немного приправлено java 8
static public void sortSequence(String inputName, String outputName) throws IOException {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(inputName), StandardCharsets.UTF_8));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputName), StandardCharsets.UTF_8))) {
List<Integer> originArray = bufferedReader.lines().map(Integer::valueOf).collect(Collectors.toList());
transform(originArray).forEach(number -> {
try {
bufferedWriter.write(number.toString());
bufferedWriter.newLine();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
}
static public Stream<Integer> transform(List<Integer> originArray) {
Map<Integer, Long> cntMap = originArray.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting()));
Map.Entry<Integer, Long> max = Collections.max(cntMap.entrySet(),
Map.Entry.<Integer, Long>comparingByValue() // максимум по value
.thenComparing(Map.Entry.<Integer, Long>comparingByKey().reversed()) // минимум по key
);
return Stream.concat(
originArray.stream().filter(x -> !x.equals(max.getKey())),
Stream.generate(max::getKey).limit(max.getValue())
);
}