피보나치, 빠른 방법!

8075 단어 algorithms

소개하다.


만약 네가 존엄성이 있다면, 너는 피보나 계수가 무엇인지 알아야 한다.만약 당신이 모른다면 피보나치 서열의 정의는 다음과 같다.
F1=F2=1
F_1=F_2=1
일층​=지상2층​=1
Fn=Fn−1+Fn−2
F_n=F_{n-1}+F_{n-2}
Fn​=Fn−1​+Fn−2​
그래서 전 6개의 피포나 계수는 1, 1, 2, 3, 5, 8이다.
우리는 n번째 피보나 계수를 계산하기 위해 알고리즘을 쓰고 싶다.

단순 저효율


이 문제의 가장 유명한 해결 방안 중 하나는 분명히 귀착된 것이다.
def fib(n):
  if n == 1 or n == 2:
    return 1
  return fib(n-1) + fib(n-2)
시간 복잡도는
O(2n)O(2^n)O(2n)
이것은 우리의 가장 무서운 악몽이다.

단순성 및 효율성


또 다른 모두가 알고 있는 해결 방안은 간단한 for 순환을 사용하는 것이다.
def fib(n):
  a = b = 1
  for i in range(n-1):
    c = a + b
    a = b
    b = c
  return a
이것은 실행할 때 상대적으로 간단하고 효율적이기 때문에 매우 좋은 해결 방안이다
O(n)O(n)O(n)
.
하지만, 우리가 더 잘할 수 있을까?
그래, 우리는 할 수 있어!

휘황찬란하다


이것은 algo holics를 위해 설계한 것이다. 그의 단순성과 효율 때문에 나는 그것이 뛰어난 해결 방안이라고 생각한다.
우리는 중에서 n번째 피보나 계수를 찾을 것이다
O(log(n))O(log(n))O(log(n))
!

고효율 파워 알고리즘


우선 어떻게 계산하는지 봅시다
xnx^nxn
효과적인 시간 복잡도
O(log(n))O(log(n))O(log(n))
.
이 알고리즘은 다음과 같은 사실에 기초를 두고 있다.
하면, 만약, 만약...
nnn
예.
평범하다
:
xn=xn/2∗xn/2x^n=x^{n/2}*x^{n/2}xn=xn/2∗xn/2
하면, 만약, 만약...
nnn
예.
이상했어
:
xn=x(n−1)/2∗x(n)−1)/2∗xx^n=x^{(n-1)/2}*x^{(n-1)/2}*xxn=x(n−1)/2∗x(n)−1)/2∗x
def pow(x, n):
  if n == 0:
    return 1
  if n % 2 == 0:
    return pow(x, n/2) ** 2
  else:
    return x * pow(x, (n-1)/2) ** 2
코스트
포로(x,n)포로(x,n)포로(x,n)
예.
O(1)O(1)O(1)
+
포로(x,n/2) 포로(x,n/2) 포로(x,n/2)
간단한 계산은 이 알고리즘의 시간 복잡도는
O(log(n))O(log(n))O(log(n))
.
너무 좋아요!그런데 이게 무슨 도움이 될까요?그것은 피보나 계수와 무슨 관계가 있습니까?너는 곧 알게 될 거야!

유효 피보나치


아래의 등식을 살펴보자. 그것은 각 상황에 적용된다
n> 2n>2n>2
:
(fn)−1) =(1110)(Fn−1Fn−2)
\bigg({F{n}\Top F{n-1}}\bigg)=\bigg({1\Top 1}{1\Top 0}\bigg)\bigg({F{n-1}\Top F{n-2}\bigg)
(Fn−1​Fn​​)=(11​01​)(Fn−2​Fn−1​​)
확인을 위해 행렬 곱셈을 계산해 봅시다.
(1110)(Fn)−1Fn−2) =(Fn−1+Fn−2Fn−1) =(fn)−1)
\bigg({1\top 1}{1\top 0}\bigg)\bigg({F_{n-1}\top F_{n-2}\bigg)=\bigg({F_{n-1}+F_{n-2}\top F_{n-1}\bigg
(11​01​)(Fn−2​Fn−1​​)=(Fn−1​Fn−1​+Fn−2​​)=(Fn−1​Fn​​)
왜냐하면 이게 모든 사람에게 옳기 때문이죠.
n> 2n>2n>2
다음과 같이 주장할 수 있습니다.
(Fn−1Fn−2) =(1110)(Fn−2Fn−3)
\{F}-big{1\g}
(Fn−2​Fn−1​​)=(11​01​)(Fn−셋​Fn−2​​)
(Fn−2Fn−3) =(1110)(Fn−3Fn−4)
\bigg({F{n-2}\Top F{n-3}}\bigg)=\bigg({1\Top 1}{1\Top 0}\bigg)\bigg({F{n-3}\Top F{n-4}\bigg)
(Fn−셋​Fn−2​​)=(11​01​)(Fn−4​Fn−셋​​)

\vdots

(F3F2)=(1110)(F2F1)=(1110)(11)=(21)
\bigg({F{3}\Top F{2}}\bigg)=\bigg({1\Top 1}{1\Top 0}\bigg)\bigg({F{2}\Top F{1}\bigg)=\bigg({1\Top 1}{1\Top 0}\bigg)\bigg({1\Top 1}\bigg
(F2)​F3​​)=(11​01​)(F1)​지상2층​​)=(11​01​)(11​)=(12​)
이제 우리 그것들을 함께 놓자.
(fn)−1) =(1110)(Fn−1Fn−2)
\bigg({F{n}\Top F{n-1}}\bigg)=\bigg({1\Top 1}{1\Top 0}\bigg)\bigg({F{n-1}\Top F{n-2}\bigg)
(Fn−1​Fn​​)=(11​01​)(Fn−2​Fn−1​​)
(fn)−1) =(1110)(1110)(Fn)−2Fn−3)
\bigg({F{n}\top F{n-1}}\bigg)=\bigg({1\top 1}{1\top 0}\bigg)\bigg({1\top 1}{1\top 0}\bigg)\bigg({F{n-2}\top F{n-3}\bigg
(Fn−1​Fn​​)=(11​01​)(11​01​)(Fn−셋​Fn−2​​)
(fn)−1) =(1110)(1110)(1110)(Fn)−3Fn−4)
\bigg({F{n}\top F{n-1}}\bigg)=\bigg({1\top 1}{1\top 0}\bigg)\bigg({1\top 1}{1\top 0}\bigg)\bigg({1\top 1}{1\top 0}\bigg)\bigg
(Fn−1​Fn​​)=(11​01​)(11​01​)(11​01​)(Fn−4​Fn−셋​​)

\vdots

(fn)−1) =(1110)n−2(F2F1)
\bigg({F{n}\Top F{n-1}}\bigg)={\bigg({1\Top 1}{1\Top 0}\bigg)}^{n-2}\bigg({F{2}\Top F{1}\bigg)
(Fn−1​Fn​​)=(11​01​)n−2(F1)​지상2층​​)
(fn)−1) =(1110)n−2(11)
\bigg({F{n}\top F{n-1}}\bigg)={\bigg({1\top 1}{1\top 0}\bigg)}^{n-2}\bigg({1\top 1}\bigg)
(Fn−1​Fn​​)=(11​01​)n−2(11​)
지금, 우리가 만약 n번째 피보나 계수(이전의 그것과)를 알고 싶다면, 우리는 단지 행렬 곱셈만 할 수 있다!더욱 구체적으로 말하면, 우리는 행렬을
n−2n-2n−2
하지만 우리는 이미 어떻게 계산하는지 알고 있다
포로(x,n)포로(x,n)포로(x,n)
에서
O(log(n))O(log(n))O(log(n))
이것은 정말 놀랍다!모든 행렬 곱셈은
O(1)O(1)O(1)
.
그래서 만약에 우리가 멱 알고리즘을 조정하고 행렬 곱셈으로 일반적인 곱셈을 대체한다면 우리는 계산할 수 있다
(1110)n−2{\big({1\top 1}{1\top 0}\big)}{n-2}(11​01​)n−2
에서
O(log(n))O(log(n))O(log(n))
곱하기
(11)\big({1\1}\big)(11​)
봐라!우리는 둘을 계산했다
FnF_nFn​

Fn−1F_{n-1}Fn−1​
에서
O(log(n))O(log(n))O(log(n))
!
시간을 좀 써서 그것을 물에 가라앉히다😌.

보너스


그래서 1분 동안 미친 듯이 기뻐하는 마음을 풀고 피보나치가 뭐가 특별한지 생각해 보세요.또는 이런 방법은 모든 귀속 방정식, 예를 들어 피보나치 방정식에 적용됩니까?
비록 피보나치는 매우 특수하지만, 이런 방법은 모든 피보나치와 유사한 방정식에 적용된다.예를 들어, Zigi 시퀀스를 다음과 같이 정의합니다.
Z1=7
Z_1=7
Z1​=7
Z2=−4
Z_2=-4
Z2​=−4
아연=2∗아연−1−셋∗아연−2
Z_n=2*Z_{n-1}-3*Z_{n-2}
아연​=2∗아연−1​−셋∗아연−2​
비결은 간단하다. 정확한 행렬을 찾으면 마법이 찾아온다.여기서 우리는 다음과 같은 것을 볼 수 있다.
(ZnZn)−1)=(21−30)(아연−1Zn−2)
\bigg({Z_{n}\top Z_{n-1}}\bigg)=\bigg({2\top 1}{-3\top 0}\bigg)\bigg({Z_{n-1}\top Z_{n-2}\bigg)
(아연)−1​아연​​)=(12​0−셋​)(아연)−2​아연−1​​)

\vdots

(ZnZn)−1)=(21−30)n−2(7−4)
\bigg({Z{n}\top Z{n-1}}\bigg)={\bigg({2\top 1}{-3\top 0}\bigg)}^{n-2}\bigg({7\top-4}\bigg)
(아연)−1​아연​​)=(12​0−셋​)n−2(−47​)
보시다시피 n'th Zigi의 숫자는
O(log(n))O(log(n))O(log(n))
.

시간 내주셔서 감사합니다.❤️!

좋은 웹페이지 즐겨찾기