Всъщност е доста интересно (все още се чудя защо никой по-умен от мен не е отговорил досега). Моля, приемете това обяснение със зърно сол, тъй като не съм 100% сигурен, че е дори близо до правилното (въпреки че мога да ви кажа със 100%, че този метод работи в O(n), тъй като това ми казаха в Университет преди години, но те не си направиха труда да го обяснят, така че трябваше да го измисля сам).
Добре, така че нека започнем с много основен пример за s.length = 2. Две неща, които трябва да споменем предварително:
- по време на всеки пример позволяваме да се тревожим само за най-лошия сценарий, тъй като се интересуваме от Big Oh, което означава, че влизаме във втория метод preLength().
- можем да наблюдаваме, когато търсим Big Oh, че "k" (и стойностите, върнати от preLength()) в този код винаги ще бъде 0, което ще забележите в изображенията по-долу и което е наистина em> важно.
s.length == 2
Първо въвеждаме първия метод preLength() (нека го наречем *), който сега се извиква с s.length = 1 и се връща веднага с 0. Сега, тъй като обмисляме само най-лошия сценарий (което означава s.charAt( k) != s.charAt(n-1)) въвеждаме втория preLength() също с низ с дължина = 1 (тъй като n=2 и k=0). Този също връща 0 незабавно към нашия *. Това приключва извикването на нашия метод. Общо имахме 3 извиквания на метода. Нашият * и два preLength(). Ето едно изображение:
![въведете описание на изображението тук](https://i.stack.imgur.com/h7Md7.png)
s.length == 3
Сега нека разгледаме пример с начален s.length = 3. Както можете да забележите, ние незабавно извикваме preLength() с s.length = 2 и от предишния ни пример знаем, че този се нуждае от 3 извиквания на метода. Сега трябва да запомним, че когато методът preLength(2) се върне този път, той се връща към нашия собствен preLength(3), който сега ще извика отново preLength(2) (този в else), който отново ще се нуждае от 3 извиквания на метода. Така че общо имаме нужда от 2*3+1 извиквания на метод. Това ни дава 7. Отново, ето изображение (кръгът е извикване на preLength с низ с дължината, показана в кръга):
![въведете описание на изображението тук](https://i.stack.imgur.com/PEzjh.png)
Изводи
Сега, както можете да видите, всички тези извиквания на методи са симетрични - и това е така, защото нашето k
е винаги равно на 0, което означава, че вторият preLengt() ще бъде извикан с низ със същия размер като първия - и можем да видим колко от тях ще са ни необходими за s.length = m
, когато знаем колко от тях са ни необходими за m-1
от f(m) = 2*f(m-1)+1
, където f(m)
е функцията, която ни казва колко извиквания на метода ни трябват, за да изчислим таблицата за низ от размер m
. Това работи, тъй като както казах преди, извикванията на метода са симетрични (това е, защото в най-лошия случай k=0 винаги и preLenght() винаги връща 0, следователно 2* и трябва да добавим 1 извикване на метод, първият, който някога извикваме).
Така че основно с всяко увеличение на нашия вход (размер на m
) изчислителното време нараства 2 пъти плюс едно (2*m+1), което според моите разбирания означава, че този метод е в най-лошия случай O(n).
Както казах, моля, приемете това със зърно сол, но се надявам, че има някакъв смисъл :)
person
Mateusz Dymczyk
schedule
05.08.2012