2013-06-28 5 views
1

У меня есть многомерный массив дат, строго ArrayList<ArrayList<Date>>. Мне нужно создать новый одномерный ArrayList<Date>, состоящий из элементов во всех массивах вышеупомянутого многомерного.Получение N отсортированных элементов из массива отсортированных массивов

Моя первая мысль состояла в том, чтобы объединить всех арраистов и отсортировать их, но так как я не знаю количества элементов на каждом уровне и нуждаюсь только в определенном количестве элементов в сгенерированном массиве, это было бы бит слишком большой объем памяти и процессора. Я имею в виду, если я присоединяюсь ко всем Date элементам в одном ArrayList<Date>, я мог бы закончить работу с тысячами дат в аранжировщике ... чтобы в конце концов подрезать его до первого 20. Вот почему я отказался от этого решения.

Итак, какой алгоритм я мог использовать для сортировки элементов из N (или 2) уровней в 1?

Редактировать

ArrayList<Date> a1 = new ArrayList<Date>(); 
a1.add(new Date(15)); 
a1.add(new Date(16)); 
a1.add(new Date(23)); 

ArrayList<Date> a2 = new ArrayList<Date>(); 
a2.add(new Date(1)); 
a2.add(new Date(25)); 
a2.add(new Date(89)); 

ArrayList<Date> a3 = new ArrayList<Date>(); 
a3.add(new Date(64)); 
a3.add(new Date(72)); 
a3.add(new Date(73)); 

ArrayList<ArrayList<Date>> b = new ArrayList<ArrayList<Date>>(); 
b.add(a1); 
b.add(a2); 
b.add(a3); 

Мне нужно реализовать getLatestDates(ArryList<ArrayList<Date>>, Integer) таким образом, что бы вернуть это:

getLatestDates(b, 5) = {Date (89), Date(73), Date(72), Date(64), Date(25)}; 

В этом примере есть только 3 ArrayList, но на практике я не буду знайте номер, поэтому я не думаю, что лучшим решением для мобильного устройства является объединение всех арраистов второго уровня и сортировка нового большого, если будет использоваться только несколько элементов.

+1

'Мне нужно генерировать ...'. Это произойдет, только если вы ** попробуете **. – devnull

+0

Не могли бы вы уточнить? Похоже, что вы решили (мысленно по крайней мере) это правильно и сказали, что это не то, что вы хотите. –

+0

Между строками я читал, что вам нужны первые 20 дат, а не сортировка всего списка. Это другой вопрос и имеет более быстрое решение, чем сортировка. Пожалуйста, ясно, что вы хотите. –

ответ

2

В соответствии с вашим описанием проблемы, некоторые решения я могу думать о том, являются:

  1. Ofcourse одного вы предложили, т.е. добавление всех массивов, а затем сортировать их и принимать первые 20 из них.
  2. Отсортируйте каждый из этих внутренних массивов индивидуально, а затем выполните процедуру слияния, как процедура, из алгоритма сортировки слияния, чтобы объединить первые 20 элементов из всех этих внутренних массивов и вырваться из цикла слияния при каждом желаемом количестве элементов (например, 20 элементов).
  3. Сортировка каждой из этих внутренних массивов при помещении в них дат. Чтобы вам не пришлось перебирать все последующие слова. Затем выполните процедуру слияния, как указано выше.

Если у вас есть несколько элементов в нескольких внутренних массивах, и вы хотите, чтобы у них было 20 первых, вам придется проходить через внутренние массивы так или иначе. Это три решения, которые я могу придумать, кто-то еще может добавить мой пост.

Edit:

4. Еще один подход, который я могу думать: строить очереди приоритета (мин кучи) путем сканирования всего массива внутренних массивов. Это будет дерево с ограничением глубины, т. Е. Поскольку вам нужно 20 элементов, максимальная глубина дерева может быть 4 (при условии, что корень равен 0). и максимальное количество разрешенных элементов в вашей куче будет 20. Этот подход даст вам решение в O (log N) времени. Конечно, вы потратите время O (N) на сканирование каждого предмета из всего списка и построение этой кучи может занимать дополнительное пространство.

+1

Точка 2 звучит довольно intreresting. Не огромное количество дат, а не турнир ... кажется разумным ... – Jago

+0

Да, но этот подход может ухудшиться, если есть много внутренних массивов со многими элементами. Единственное преимущество, которое у вас будет тогда, - худшее время для сортировки слияния, по-прежнему O (N log N), поэтому его по-прежнему выигрыш. Поэтому выбирайте разумно. – tejas

+0

Если вы планируете 2), хотите получить решение с довольно низкими затратами на программирование и чувствовать себя нормально с сложностью O (n * logn), попробуйте собрать все свои даты в TreeMap, которые будут сортировать их автоматически. Затем вы можете вызвать myTreeMap.firstKey() n раз. Если вы хотите удалить дубликаты, вместо этого используйте TreeSet. – LastFreeNickname

0

Я бы предложил tournament algorithm. Это может быть довольно сложно, но даст вам время работы, линейное в всего количество элементов.

Я бы действовать следующим образом:

  1. Есть турнир для каждого списка и сохранить дерево турнира (это дерево может быть довольно тривиально: для каждого элемента, сохранить список противников и результат)
  2. Have турнир между победителями и хранить турнира дерева
  3. Первым элементом является победителем турнира 2
  4. Второй элемент находится среди проигравших победителя в любом турнире 1 или 2 турнира
  5. Третий элемент среди проигравших NR2 в любом турнире 1 или 2 турнира
  6. И так далее ...
+0

Звучит неплохо. Мне просто интересно, может ли это быть еще более ресурсоемким в мобильном устройстве, чем слияние всех элементов в одном массиве и сортировка его ...? – Jago

+1

@Jago Это хороший вопрос. Хранилище будет 'O (n)', но я не совсем уверен в константе. И вам нужен массив * огромный * до того, как линейный алгоритм с плохими константами превзойдет алгоритм 'n log n' с хорошими константами (например, быстрым сортированием по умолчанию). Тем не менее, вы можете рассмотреть этот подход, когда вы сталкиваетесь с проблемами производительности, потому что у вас очень много дат. –

+0

Я думаю, что этот подход занимает слишком много места, и, учитывая, что это сделано в мобильном телефоне, его почти невозможно. – tejas