簡體   English   中英

Codility FibFrog 算法 - 將時間復雜度從 O(N * log(N) ** N) 提高到 O(N*log(N))

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM