[英]Codility FibFrog Algorithm - Improving Time Complexity from O(N * log(N) ** N) to O(N*log(N))
我正在嘗試解決 Codility FibFrog問題,我想出了以下解決方案:
def jumps_from(position, fb, A):
paths = set([])
for i in fb:
newPos = position + i
if newPos == len(A):
return set([-1])
elif newPos < len(A):
if A[newPos] == 1:
paths.add(newPos)
else: break
return paths
def solution(A):
if len(A) < 3: return 1
fibonaccis = fibonacci(len(A))
if len(A) + 1 in fibonaccis: return 1
paths = set([-1])
steps = 0
while True:
paths = set([idx for pos in paths for idx in jumps_from(pos, fibonaccis, A)])
if len(paths) == 0: return -1
if -1 in paths:
return steps + 1
steps += 1
return steps
def fibonacci(N):
arr = [0] * (N + 2)
arr[1] = 1
for i in range(2, N + 2):
arr[i] = arr[i-1] + arr[i-2]
return dict.fromkeys(arr[2:], 1)
Codility 將其運行時間檢測為O(N * log(N) ** N)
。
代碼報告: https://app.codility.com/demo/results/trainingJV7YAC-G3B/
我將此與以下解決方案進行比較,該解決方案在 Codility 上得分 100%,並且運行時間為O(N * log(N))
:
def gen_fib(n):
fn = [0,1]
i = 2
s = 2
while s < n:
s = fn[i-2] + fn[i-1]
fn.append(s)
i+=1
return fn
def new_paths(A, n, last_pos, fn):
"""
Given an array A of len n.
From index last_pos which numbers in fn jump to a leaf?
returns list: set of indexes with leaves.
"""
paths = []
for f in fn:
new_pos = last_pos + f
if new_pos == n or (new_pos < n and A[new_pos]):
paths.append(new_pos)
return paths
def solution(A):
n = len(A)
if n < 3:
return 1
# A.append(1) # mark final jump
fn = sorted(gen_fib(100000)[2:]) # Fib numbers with 0, 1, 1, 2.. clipped to just 1, 2..
# print(fn)
paths = set([-1]) # locate all the leaves that are one fib jump from the start position.
jump = 1
while True:
# Considering each of the previous jump positions - How many leaves from there are one fib jump away
paths = set([idx for pos in paths for idx in new_paths(A, n, pos, fn)])
# no new jumps means game over!
if not paths:
break
# If there was a result in the new jumps record that
if n in paths:
return jump
jump += 1
return -1
我不確定為什么我的解決方案在運行時有所不同,因為方法完全相同 - 計算可以從-1
跳轉到的所有索引,然后計算可以從新位置跳轉到的所有索引,直到你得到到河的另一邊,否則找不到新的位置。
請參考我之前回答的第一點。
如果 len(A) = 100000,您正在計算 100003 個斐波那契數,而我們只需要小於 100k 的斐波那契數,即少於 30 個。
當前的fibonacci
那契 function 仍在返回N
斐波那契數,而不是僅返回小於N
的斐波那契數。 對於N=100k
,它應該只有 25 個數字,而不是超過 100k。
請將您的fibonacci
那契 function 更新為此 -
def fibonacci(N):
arr = [1, 1]
while arr[-1] < N:
arr.append(arr[-1] + arr[-2])
return dict.fromkeys(arr[1:], 1)
我剛剛在本地運行了一個測試,看起來你的fibonacci
那契 function 需要大約 1 秒來生成前 100k 斐波那契數字,這就是它可能未能通過性能測試的原因,即使你的代碼的 rest 是最佳的。 我認為在糾正fibonacci
那契 function 之后,您應該能夠使用所需的性能限制來清除它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.