2015-03-14 2 views
4

Это вопрос: https://leetcode.com/problems/combinations/Java ArrayList клон улучшил время выполнения

Это мое решение 1:

public class Solution { 

    public List<List<Integer>> combine(int n, int k){ 
     List<List<Integer>> result = new ArrayList<List<Integer>>(); 
     combine(n, k, 1, result, new ArrayList<Integer>()); 
     return result; 
    } 

    public void combine(int n, int k , int start, List<List<Integer>> result, ArrayList<Integer> l){ 
     if(k == 0){ 
      result.add(l); 
      return; 
     } 
     for(int i = start; i <= n; ++i){ 

      l.add(i); 
      combine(n, k - 1, i + 1, result, l); 
     } 
    } 


    } 

Результат: небольшие тестовые случаи прошли. Но большие времена испытаний превышают.

Подача Результат: Лимит времени Превышен Последний выполнен вход: 10, 5

Решение 2:

public class Solution { 

public List<List<Integer>> combine(int n, int k){ 
    List<List<Integer>> result = new ArrayList<List<Integer>>(); 
    combine(n, k, 1, result, new ArrayList<Integer>()); 
    return result; 
} 

public void combine(int n, int k , int start, List<List<Integer>> result, ArrayList<Integer> l){ 
    if(k == 0){ 
     result.add(l); 
     return; 
    } 
    for(int i = start; i <= n; ++i){ 
     ArrayList<Integer> a = (ArrayList<Integer>) l.clone(); 
     a.add(i); 
     combine(n, k - 1, i + 1, result, a); 
    } 
} 


} 

Сдал все тестовые случаи.

Главное отличие - это клон списка. Но почему? Решение является неправильным или просто медленным? Почему использование клона здесь быстрее? Действительно смущен.

+0

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

ответ

3

Первое решение действительно неверно. Попробуйте ссылаться combine(5,3), и отправить его в System.out, и вы увидите выход для первой является:

[[1, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5, 2, 3, 4, 5, 4, 5, 5, 3, 4, 5, 5, 4, 5, 5], [1, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5, 2, 3, 4, 5, 4, 5, 5, 3, 4, 5, 5, 4, 5, 5], [1, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5, 2, 3, 4, 5, 4, 5, 5, 3, 4, 5, 5, 4, 5, 5], [1, 2, 3, 4, 5, 3, 4, 4, 5, 5, 5, 4, 5, 5, 5, 4, 5, 4, 5, 5, 2, 3, 4, 5, 4, 5, 5, 3, 4, 5, 5, 4, 5, 5], [1, 2, 3, 4, 5, 4, 5, 5, 4, 5, 5, 5, 5, 3, 4, 5, 4, 5, 5, 2, 3, 4, 5, 4, 5, 5, 3, 4, 5, 5, 4, 5, 5], [1, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5, 2, 3, 4, 5, 4, 5, 5, 3, 4, 5, 5, 4, 5, 5], [1, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5, 2, 3, 4, 5, 4, 5, 5, 3, 4, 5, 5, 4, 5, 5], [1, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5, 2, 3, 4, 5, 4, 5, 5, 3, 4, 5, 5, 4, 5, 5]]

Вы заметите, что это один и тот же список в каждой позиции индекса - вам действительно нужно создавать новый массив каждый раз. Для второго правильного решения выход:

[[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5], [2, 3, 4], [2, 3, 5], [2, 4, 5], [3, 4, 5]]

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

+0

Как он мог исправить первое решение? Что он умеет? Благодарю. – Unheilig

+1

@Unheilig Исправление состоит в том, чтобы создавать новый массив каждый раз, что он и делает во втором решении. –

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