Мы не можем использовать ArrayList
или что-то в этом роде, потому что учитель сказал нам не использовать их, поэтому я застрял на этом этапе. Сигнатура функции:
public static int[] deleteNth(int[] elements, int maxOccurrences){}
Я уже просматриваю массив и получаю длину скопированного int result[]
, который я верну, но теперь я застрял, думая, как я могу вставить определенные элементы. Я написал ввод-вывод метода:
deleteNth(new int[] {20,37,20,21}, 1) // return [20,37,21]
deleteNth(new int[] {1,1,3,3,7,2,2,2,2}, 3) // return [1, 1, 3, 3, 7, 2, 2, 2]
В последний шанс для меня я пробую что-то вроде этого, но мои мозги выгорают
for(int n:result) {
int n1=0;
boolean nope=false;
for(;n1<elements.length;) {
//TODOthings
}
result[n]=elements[n1];
}
Для тех, кто мне не верит, вот мой код:
public static int[] deleteNth(int[] elements, int maxOccurrences) {
int[] result = null;
if (elements != null && maxOccurrences > 0) {
int result_lenght=elements.length;
int ocurrences=0;
for(int n:elements) {
for(int n1:elements) {
if(n==n1 && ocurrences!=maxOccurrences) {
ocurrences++;
result_lenght--;
}
}
}
result=new int[result_lenght];
for(int n:result) {
int n1=0;
boolean nope=false;
for(;n1<elements.length;) {
//todothings
}
result[n]=elements[n1];
}
}else {
result=elements;
}
return result;
}
3 ответа
Возможное простое решение (хотя и неэффективное) - начать с создания метода, который принимает в качестве параметра массив, количество элементов в нем и значение и возвращает количество раз, когда значение появляется в массиве, что-то вроде :
int total_occurences(int[] elements, int size, int value)
Используйте этот метод в своем основном коде:
int copy[] = new int [elements.length];
int elements_copied = 0;
for(int i = 0; i < elements.length; i++) {
// Check if you are "allowed" to copy the element
if(total_occurences(copy, elements_copied , value <= maxOccurrences){
copy[elements_copied] = element[i];
elements_copied ++;
}
}
// copy the content to a new array of size = elements_copied
// return that array
Основная идея состоит в том, чтобы сначала создать массив ( т.е. int copy[] = new int [elements.length]
) того же размера, что и массив elements
, поскольку вы заранее не знаете, сколько существует дубликатов. Выполните итерацию по массиву elements
и для текущего элемента ( т.е. element[i]
) проверьте, скопировано ли уже (этот элемент) максимально допустимое число ( т.е. maxOccurrences
):
if(total_occurences(copy, elements_copied , value <= maxOccurrences)
Если не скопировать элемент и увеличить количество скопированных элементов:
copy[elements_copied] = element[i];
elements_copied ++;
Нам нужно использовать другую переменную для итерации по массиву copy
, поскольку он может содержать другое количество элементов, чем массив elements
. Например, после того, как дублированный номер был "удален" . В конце вы можете создать новый массив (тот, который будет возвращен) с размером, равным переменной elements_copied
, и скопировать элементы из массива copy
в этот вновь созданный массив. Таким образом вы вернете массив без пропущенных значений в конце.
Поскольку никакие библиотечные средства, такие как Set
или Map
, и соответствующие реализации не могут быть использованы в этой задаче, и повторное изобретение колес для повторной реализации этих классов кажется гораздо более сложным, чем необходимо, простое решение может быть основано на использовании объектной оболочки Integer
для int
, чтобы использовать null
для отметки значений, которые должны быть удалены.
Итак, алгоритм будет следующим:
- Преобразовать ввод
int[]
вInteger[]
- Инициализируйте
nullCount
, используя вложенные циклы, обнаружите повторяющиеся значения, превышающие порог, и установите их наnull
вместе с увеличениемnullCount
- Создайте массив результатов, скопируйте ненулевые значения и верните его.
Пример реализации:
public static int[] deleteNth(int[] elements, int maxOccurrences) {
Integer[] arr = new Integer[elements.length];
int i = 0;
for (Integer x : elements) {
arr[i++] = x;
}
int nullCount = 0;
for (i = 0; i < arr.length; i++) {
Integer x = arr[i];
if (null == x) {
continue;
}
int cnt = 1;
for (int j = i + 1; j < arr.length; j++) {
Integer y = arr[j];
if (null == y) {
continue;
}
if (x.equals(y)) {
cnt++;
if (cnt > maxOccurrences) {
arr[j] = null;
nullCount++;
}
}
}
}
int[] result = new int[arr.length - nullCount];
i = 0;
for (int j = 0; j < arr.length; j++) {
Integer x = arr[j];
if (null != x) {
result[i++] = x;
}
}
return result;
}
Тест и вывод:
System.out.println(Arrays.toString(deleteNth(new int[] {20,37,20,21}, 1))); // return [20,37,21]
System.out.println(Arrays.toString(deleteNth(new int[] {1,1,3,3,7,2,2,2,2}, 3))); // return [1, 1, 3, 3, 7, 2, 2, 2]
Выход:
[20, 37, 21]
[1, 1, 3, 3, 7, 2, 2, 2]
Более быстрая версия может использовать дополнительный логический массив для отслеживания повторяющихся значений, чтобы их можно было пропустить во вложенном цикле.
Решение на основе потока (только для справки и сравнения) будет таким:
- подготовить начальную карту с элементами массива в качестве ключей, а значение - список индексов, используя
Collectors.groupingBy
- переназначить записи в исходной карте: index -> key (элемент массива) с помощью
flatMap
иStream::limit
для соблюдения порогового значения - отсортировать новые записи по индексу
- получить значения и собрать их в массив
public static int[] deleteNth(int[] arr, int threshold) {
return IntStream
.range(0, arr.length)
.boxed()
.collect(Collectors.groupingBy(
i -> arr[i],
Collectors.mapping(i -> i, Collectors.toList())
))
.entrySet()
.stream()
.flatMap(e -> e.getValue().stream()
.limit(threshold)
.map(ix -> Map.entry(ix, e.getKey())) // Map.entry since Java 9
)
.sorted(Map.Entry.comparingByKey())
.mapToInt(Map.Entry::getValue)
.toArray();
}
Вы можете сделать это с помощью HashMap
, чтобы отслеживать количество появлений каждого числа:
public static int[] deleteNth(int[] elements, int maxOccurrences){
// get number of occurrences of each number in elements less than max
Map<Integer,Integer> occurences = new HashMap<>();
for(int element : elements) {
int count = occurences.containsKey(element) ? occurences.get(element) : 0;
if(count < maxOccurrences) occurences.put(element, count+1);
}
// calculate total size of array to return
int size = 0;
for(int numberOccurences : occurences.values()) size += numberOccurences;
int[] res = new int[size];
// clear map to reuse it
occurences.clear();
// reiterate over elements array
int i = 0;
for(int element : elements) {
int count = occurences.containsKey(element) ? occurences.get(element) : 0;
// add number to resulting array if its count in it is still less than max
if(count < maxOccurrences) res[i++] = element;
occurences.put(element, count+1);
}
return res;
}
Похожие вопросы
Новые вопросы
java
Java - это язык программирования высокого уровня. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег редко используется отдельно и чаще всего используется вместе с [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] и [maven].