2013-09-18 4 views
3

Так что я пытаюсь решить эту проблему: http://oj.leetcode.com/problems/merge-intervals/Leetcode: почему этот алгоритм работает медленно?

Моего решения:

public class Solution { 

public ArrayList<Interval> merge(ArrayList<Interval> intervals) { 
    // Start typing your Java solution below 
    // DO NOT write main() function 
    // ArrayList<Interval> result = new ArrayList<Interval>(); 

    //First sort the intervals 
    Collections.sort(intervals,new Comparator<Interval>(){ 
     public int compare(Interval interval1, Interval interval2) { 
      if(interval1.start > interval2.start) return 1; 
      if(interval1.start == interval2.start) return 0; 
      if(interval1.start < interval2.start) return -1; 
      return 42; 
     } 
    }); 

    for(int i = 0; i < intervals.size() - 1; i++){ 
     Interval currentInterval = intervals.get(i); 
     Interval nextInterval = intervals.get(i+1); 
     if(currentInterval.end >= nextInterval.start){ 
      intervals.set(i,new Interval(currentInterval.start,nextInterval.end)); 
      intervals.remove(i+1); 
      i--; 
     } 
    } 

    return intervals; 
} 
} 

Я видел некоторые блог, используя точно такое же решение, но получить признание, но мой отвергаются, потому что это занимает слишком много времени. Можете ли вы рассказать мне, почему это занимает больше времени, чем ожидалось? Приветствия

EDIT: решил, удалить слишком дорого, используя новый ArrayList для хранения результата быстрее

+1

Что говорит профайлер? – SpongeBobFan

+3

Этот вопрос не соответствует теме, потому что речь идет о [codereview] (http://codereview.stackexchange.com/). – Sirko

+3

Удаление из головы -> середины массива довольно дорого, потому что основной массив должен быть скопирован при каждом вызове. Но @SpongeBobFan сказал, вы должны проверить это с помощью профилировщика. –

ответ

2

Первоначально вы сортируете все свои интервалы - из-за javadocs эта операция имеет сложность O (N * log (N))

Но после этого, как я заметил, вы повторяете ArrayList и иногда удаляете элементы из Это.

Но удаление какого-либо элемента из ArrayList имеет complexity O(N) (поскольку базовая реализация ArrayList - это простой массив - удаление любого элемента из середины массива требует сдвига всей правой части этого массива).

Как вы это делаете в цикле - наконец, сложность вашего альгирима будет O (N^2).

Я предлагаю вам использовать LinkedList вместо ArrayList в этом случае.

+2

Или, может быть, даже умнее: вместо проверки только следующего элемента он может проверить, пока он найдет сменный элемент, а затем поместите в результате объединенный интервал в новый список. Я думаю, где '// ArrayList result = new ArrayList ();' происходит. –

+2

Решил использовать то, что предложил @ThomasJungblut, сохранить его в новом ArrayList, спасибо всем :) – dorafmon

1

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

Collections.sort(intervals,new Comparator<Interval>(){ 
    public int compare(Interval interval1, Interval interval2) { 
     return interval1.start - interval2.start; 
    } 
}); 
+0

Улучшите, в каком направлении? –

+0

@BorisTreukhov Меньше операций. Внутри каждого сравнения, вероятно, будет по крайней мере одно вычисление, подобное тому, которое я использовал. Таким образом, сокращение количества операций здесь должно улучшить время выполнения в целом. – Sirko

+2

TimSort худший случай n * logn, очевидно проблема заключается в удалении из середины массива –

Смежные вопросы