【问题标题】:FibFrog Codility Problem - Optimising for PerformanceFibFrog Codility Problem - 性能优化
【发布时间】:2021-12-30 21:55:33
【问题描述】:

我正在尝试解决FibFrog Codility 问题,我想出了以下方法:

  1. 如果len(A) 为 0,我们知道我们可以一次跳跃到达另一边。
  2. 如果len(A) + 1是一个斐波那契数,我们也可以一跳就到。
  3. 否则,我们遍历 A,对于我们可以到达的位置,我们检查是否可以使用斐波那契数 (idx + 1 in fibonaccis) 从 -1 直接到达它们,或者我们是否可以通过首先跳转到另一个位置来到达它们 ( reachables) 然后跳转到当前位置。在这两种情况下,我们还会检查是否可以从当前位置走到河流的尽头 - 如果可以,那么我们可以返回,因为我们找到了所需的最少步数。
  4. 最后,如果 unreachableTrue,一旦此循环完成,这意味着我们无法使用斐波那契数到达任何位置,因此我们返回 -1。

我是getting 83% 的正确性和 0% 的性能使用这种方法。

我知道解决方案是 O(n^2),假设数组仅包含 1,嵌套循环 for v in reachables: 将运行 n 次 - 但是我不确定我还能如何计算它,因为对于我需要检查的每个位置是否可以从数组的开头或使用斐波那契数的任何先前位置到达。

    def solution(A):
        if len(A) == 0: return 1 
        fibonaccis = fibonacci(len(A) + 3)
        if len(A) + 1 in fibonaccis: return 1
        leaves = [0] * len(A)
        unreachable = True
        reachables = []
        for idx, val in enumerate(A): 
            if val == 1: 
                if idx + 1 in fibonaccis: 
                    unreachable = False
                    leaves[idx] = 1
                    if len(A) - idx in fibonaccis: 
                        return 2
                    reachables.append(idx)
                elif len(reachables) > 0: 
                    for v in reachables: 
                        if idx - v in fibonaccis: 
                            leaves[idx] = leaves[v] + 1
                            if len(A) - idx in fibonaccis: 
                                return leaves[v] + 2
                            reachables.append(idx)
                            break
        if unreachable: return -1 
        if len(A) - reachables[-1] in fibonaccis: 
            return leaves[reachables[-1]] + 1
    
    def fibonacci(N): 
        arr = [0] * N
        arr[1] = 1
        for i in range(2, N): 
            arr[i] = arr[i-1] + arr[i-2]
        return arr

【问题讨论】:

  • 这绝对不是重复的,因为您链接的问题是在 Java 中,而且它也是一个完全不同的实现 - 我问的是我的解决方案具体有什么问题,而不是如何以不同的方式解决这个问题在 Java 中。
  • 它不起作用 - 正如我在问题中提到的那样,它有 83% 的正确性。
  • 有 O(log N) 个斐波那契数

标签: python algorithm time-complexity fibonacci


【解决方案1】:

一些提高算法性能的建议 -

  • 如果len(A) = 100000,您正在计算 100003 个斐波那契数,而我们只需要小于 100k 的斐波那契数,即
  • 您的解决方案是O(n^4),因为每个X in reachablesY in fibonaccis 操作都是O(N),其中Nlen(A)。 (由于上述问题,fibonaccis 的长度为 N
  • 由于您正在对fibonaccisreachables 执行大量item in list 操作,因此请考虑将其设置为setdictionary 以便更快(O(1) 而不是O(n))查找。
  • 即使进行了上述更改,由于 Areachables 之间存在嵌套循环,算法仍将是 O(N^2),因此您需要提出更好的方法。

使用您现有的实现,您需要遍历所有路径,然后最终您将获得最少的跳转次数。

如果您从0 开始,而不是这种方法,然后记录到目前为止您已完成的跳跃次数,并保持每次跳跃后您可以达到多远(以及达到哪些数字),那么您可以很容易地找到到达终点所需的最小跳跃。 (如果您在 A 中拥有所有 1s,这也将节省您必须做的多余工作。

例如对于

A = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
fibonacci = set(1, 2, 3, 5)

第一次跳转,我们可以达到以下从 1 开始的索引 -

reachable = [1, 2, 3, 5]
jumps = 1

第二次跳跃后

reachables = [2, 3, 4, 5, 6, 7, 8]
jumps = 2

第三跳后

reachables = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
jumps = 3

所以你在 3 次跳跃后到达了终点(10)。

请在此处查看@nialloc 的答案 - https://stackoverflow.com/a/64558623/8677071 似乎正在做类似的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-15
    • 1970-01-01
    • 2013-03-17
    • 2016-05-14
    • 2011-10-17
    • 2014-01-08
    • 1970-01-01
    • 2017-06-02
    相关资源
    最近更新 更多