Рекурсивная треугольная строка Паскаля, большая стоимость O

Я готовлюсь к собеседованию по CS и решил попробовать придумать собственную проблему и решить ее рекурсивно.

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

Ex pascals(1) -> 1
   pascals(2) -> 1,1
   pascals(3) -> 1,2,1

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

function int[] nthPascal(int[] a, int n){
  // in the case that the row has been reached return the completed array
  if(n==1){
    return a;
  }
  // each new row of pascal's triangle is 1 element larger. Ex 1, 11, 121,1331 etc. 
  int[] newA = new int[a.length()+1];

  //set the ends. Technically this will always be 1.
  // I thought it looked cleaner to do it this way. 
  newA[0]=a[0];

  newA[newA.length-1]=a[a.length-1];

  //so I loop through the new array and add the elements to find the value.
  //ex 1,1 -> -,2,- The ends of the array are already filled above
  for(int i=1; i<a.length; i++){

    // ex 1+1 = 2 for 1,1 -> 1,2,1
    newA[i]=a[i-1]+a[i]
  }
  //call the recursive function if we are not at the desired level
  return nthPascal(newA,n-1);
}

/**
*The helper function
*/
public int[] helperPascal(int n){
  return nthPascal(int[] {1},n);
}

У меня вопрос: как мне узнать стоимость bigO?

Я знаком с общими затратами алгоритмов и с тем, как их найти. Рекурсия в этом сбивает меня с толку.

Я знаю, что это явно непостоянно, n, nlogn и т. Д. Я думал, что это 3 ^ n?

Я поискал пример и нашел: Последовательность треугольных строк Паскаля и Какова продолжительность выполнения этого алгоритма? (Рекурсивный треугольник Паскаля). Но я считаю, что они пытаются найти конкретный элемент в данном месте. Я не смог найти никого, кто реализовывал бы треугольник Паскаля таким образом и говорил бы о стоимости bigO.

Это потому, что есть лучший способ написать рекурсивную строку, находящую функцию паскаля? Если да, поделитесь пожалуйста :)


person Tai    schedule 10.09.2014    source источник
comment
1) Что nthFib? 2) Правильный синтаксис для вспомогательной функции будет return nthPascal(new int[] {1}, n); 3) В Java не используйте () при вычислении длины массива (но он нужен вам для длины строки). 4) intA следует объявлять с помощью new int[...], а не int [...]. Я понимаю, что все это не имеет отношения к вашему вопросу.   -  person ajb    schedule 10.09.2014
comment
1) Ой, извините, я имел ввиду nthPascal, я сначала делал nthFibonaci. И о, спасибо за помощь по java. Прошло много времени с тех пор, как я кодировал на java, и я практикуюсь делать это без и ide   -  person Tai    schedule 10.09.2014


Ответы (2)


Каждый раз, когда вы вызываете nthPascal, он рекурсивно вызывает себя только один раз. Следовательно, вы можете получить временную сложность, добавив временную сложность каждого вызова функции (исключая рекурсивный вызов). (Если бы у вас была функция, которая проходит через двоичное дерево, она обычно вызывала бы себя рекурсивно дважды, что усложняет вычисление. Однако здесь, поскольку она вызывает себя только один раз, вычисления довольно просты.)

Каждый вызов функции имеет цикл, который выполняется a.length раз, а тело цикла выполняется за постоянное время. Нет никаких других циклов или любых других операторов, которые выполняются в чем-либо, кроме постоянного времени, за исключением случаев, когда вы выделяете массив intA, потому что Java инициализирует каждый элемент массива. Однако в результате, когда вы вызываете nthPascal с массивом длины M, время выполнения будет O (M), не считая рекурсивного вызова.

Итак, предполагая, что время выполнения составляет примерно M * k для некоторой константы k, это означает, что общее время выполнения будет 1 * k + 2 * k + 3 * k + ... + (n-1) * k. И 1 + 2 + 3 + ... + n - 1 равно (n * (n - 1)) / 2, что составляет O (n 2). Итак, O (n 2) - это ответ, который вы ищете.

person ajb    schedule 10.09.2014
comment
О, спасибо. Я ошибся. Я думаю, потому что количество значений в массиве меняется каждый раз, когда я спотыкаюсь. Спасибо! - person Tai; 10.09.2014

Для каждого рекурсивного вызова вы выполняете цикл for размером k, где k - глубина рекурсивного вызова (на глубине k у вас есть массив размером k).

Чтобы получить полную строку на глубине n, вы вызываете nthPascal на глубине 1, 2, ..., n.

Следовательно, ваша общая сложность будет 1+2+...+n=n(n+1)/2 = O(n²).

person R2B2    schedule 10.09.2014