Получить индексы n наименьших элементов в массиве
У меня есть int array int[] myArray = new int[100];
и вы хотите получить индексы наименьших 10 (любых n) элементов. Как я могу это сделать?
Ответы
Ответ 1
создайте объект, который содержит число и индекс, затем создайте массив из этих объектов, затем выполните команду Array.Sort(arrayset [], компаратор) java docs. Затем вы можете просто выбрать верхние элементы x из отсортированного массива.
EDIT:
Что-то вроде этого... [Я использовал это для сортировки по "расстоянию"
import java.util.Arrays;
import java.util.Comparator;
public class NearestObject
{
public NearestObject(int position, int distance)
{
this.Position = position;
this.Distance = distance;
}
public int Position = 0;
public int Distance = 0;
public static NearestObject[] SortDistance(NearestObject[] items)
{
Arrays.sort(items, new DistanceSort());
return items;
}
}
class DistanceSort implements Comparator<NearestObject>
{
public int compare(NearestObject o1, NearestObject o2)
{
return o1.Distance - o2.Distance;
}
}
Ответ 2
Сортировка массива, а затем выбор 10 прост, но это будет O (n log n), и если вы не захотите переупорядочить начальный массив, вам также нужно будет сделать копию.
Лучше всего использовать max-heap (или приоритетную очередь), которая автоматически сортирует элементы при их вставке, так что наибольший элемент - это корень node. Пройдите вдоль массива, продолжайте вставлять элементы, пока не нажмете 10; то для каждого последующего элемента просто проверьте, меньше ли он самого большого элемента в куче (постоянная проверка), и если это так, вытащите его и вставьте новый элемент. Когда вы пройдете весь массив, 10 вещей, оставшихся внутри, являются вашими минимальными элементами. Это даст вам результат в O (n log 10) == O (n), поскольку каждая вставка в кучу будет стоить только O (log 10).
Реализация очереди Java Priority Queue по умолчанию является мини-очередью, поэтому вам нужно будет передать в Comparator, который изменит порядок заказов. См. этот вопрос для примера о том, как это сделать. Вам нужно будет создать пользовательский объект, который содержит пары (значение, индекс), если вы хотите получить индексы в конце.
Ответ 3
Прямое решение состоит в том, чтобы перебирать массив и поддерживать список самых маленьких элементов, которые вы нашли, и их индексы. Это решение O (N) и приемлемо в большинстве случаев. Я предполагаю, что это домашняя работа, и у вас должно быть что-то лучше, чем O (N).
Ответ 4
Отсортируйте их по индексу и верните первые 10
Сначала создайте структуру для хранения как индекса, так и значения:
class IndexValue {
final int i;
final int v;
}
Затем создайте массив с этой новой структурой:
IndexValue[] array = new IndexValue[myArray.length];
for( int i = 0 ; i < array.length ; i++ ) {
array[i] = new IndexValue( i, myArray[i] );
}
Наконец, отсортируйте его и возьмите первые N элементов
Arrays.sort( array ); // you'll need to implement Comparator though
for( int i = 0 ; i< 10 ;i++ ) {
System.out.print( array[i] );
}
Здесь полный рабочий код:
import java.util.Arrays;
import java.util.Random;
import java.util.Comparator;
import static java.lang.System.out;
class IndexValue {
final int i,v;
public IndexValue( int i, int v ) {
this.i = i;
this.v = v;
}
}
public class SortByIndex {
public static void main( String [] args ) {
Random random = new Random();
int [] myArray = new int[100];
IndexValue[] array = new IndexValue[myArray.length];
// Fill the array
for( int i = 0 ; i < 100; i++ ) {
myArray[i] = random.nextInt();
array[i] = new IndexValue( i, myArray[i] );
}
// Sort it
Arrays.sort( array, new Comparator<IndexValue>(){
public int compare( IndexValue a, IndexValue b ){
return a.v - b.v;
}
});
// Print it
out.println("Top:");
for( int i = 0 ; i < 10 ; i++ ) {
out.println( String.format("array[%d]=%d", array[i].i, array[i].v ));
}
}
}
Ответ 5
Вы можете сортировать массив, зацикливать первые 10 элементов, а затем для каждого поиска элементов в массиве, в котором он имеет... возможно, это не более эффективный способ, но это проще.
Ответ 6
Если вы ищете практический ответ (по сравнению с фактическим сортировкой alg. и т.д.), просто используйте HashMap или PriorityQueue. Если скорость не вызывает беспокойства, попробуйте этот простой alg. Это проще, чем PriorityQueue, поскольку вам не нужен пользовательский объект:
HashMap<Integer, ArrayList<Integer>> indexMap = new HashMap<Integer, ArrayList<Integer>>();
Заполните индексную карту, чтобы мы могли получить индексы для любого заданного числа в массиве
for (int index = 0; index <= array.size; index++) {
if (indexMap.get(array[index]) == null) { // Prime it with an ArrayList
indexMap.put(array[index], new ArrayList<Integer>());
}
indexMap.get(array[index]).add(index);
}
Для наименьших n чисел в массиве распечатайте их индекс.
Arrays.sort(array);
for (int index = 0; index <= n; index++) {
System.out.println(indexMap.get(array[index]).remove(0));
}