Python Codility Frog River一次复杂度

时间:2018-09-28 14:23:08

标签: algorithm performance time-complexity

因此,这是可能著名的codility平台的另一种方法,即关于青蛙过河的任务。很抱歉,如果这个问题的提问方式不好,这是我在这里的第一篇文章。

  

目标是找到青蛙跳到河对岸的最早时间。   例如,给定X = 5且数组A使得:

  A[0] = 1
  A[1] = 3
  A[2] = 1
  A[3] = 4
  A[4] = 2
  A[5] = 3
  A[6] = 5
  A[7] = 4
  

该函数应返回6。

示例测试:(5,[1、3、1、4、2、3、5、4])

全部任务内容: https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/

这是我第一个显而易见的方法:

def solution(X, A):
    lista = list(range(1, X + 1))
    if X < 1 or len(A) < 1:
        return -1
    found = -1
    for element in lista:
        if element in A:
            if A.index(element) > found:
                found = A.index(element)
        else: return -1
    return found

X = 5
A = [1,2,4,5,3]
solution(X,A)

此解决方案是100%正确的,在性能测试中为0%。

所以我认为更少的行数和列表理解将获得更好的分数:

def solution(X, A):
    if X < 1 or len(A) < 1:
        return -1
    try:
        found = max([ A.index(element) for element in range(1, X + 1) ])
    except ValueError:
        return -1
    return  found

X = 5
A = [1,2,4,5,3]
solution(X,A)

这也可以并且具有0%的性能,但是无论如何它都更快。

我还发现了deanalvero(https://github.com/deanalvero/codility/blob/master/python/lesson02/FrogRiverOne.py)的解决方案:

def solution(X, A):
    # write your code in Python 2.6
    frog, leaves = 0, [False] * (X)
    for minute, leaf in enumerate(A):
        if leaf <= X:
            leaves[leaf - 1] = True
        while leaves[frog]:
            frog += 1
            if frog == X: return minute
    return -1

此解决方案通过了100%的正确性和性能测试。

之所以出现这个问题,可能是因为我不太了解这次的复杂性。请告诉我最后一个解决方案比第二个解决方案更好吗?它在for循环中有一个while循环!它应该很慢,但不是。

8 个答案:

答案 0 :(得分:2)

在这里,您将获得100%的正确性和性能。

def solution(X, A):
    i = 0
    dict_temp = {}
    while i < len(A):
        dict_temp[A[i]] = i
        if len(dict_temp) == X:
            return i
        i += 1
    return -1

答案 1 :(得分:1)

答案已经被告知,但是我将添加一个可选的解决方案,我认为它可以帮助您理解:

def save_frog(x, arr):
    # creating the steps the frog should make
    steps = set([i for i in range(1, x + 1)])

    # creating the steps the frog already did
    froggy_steps = set()

    for index, leaf in enumerate(arr):
        froggy_steps.add(leaf)
        if froggy_steps == steps:
            return index
    return -1

答案 2 :(得分:1)

这是我如何解决它并获得0个性能的方法:

def solution(X, A):
    # write your code in Python 3.6
    if X not in A: return -1 
    else: return [i for i in range(len(A)) if(A[i]==X)][0]

我只用了两行就得到了这种表现!!

答案 3 :(得分:0)

嵌套循环的数量并不能直接告诉您时间的复杂性。假设 n 为输入数组的长度。 while循环内部需要平均值 O(1)时间,尽管最坏情况下的时间复杂度是 O(n)。快速解决方案使用布尔数组 leaves ,其中在每个索引中,如果有叶子,则其值为 true ,否则为 false 。在整个算法中,while循环的内部不超过 n 次。外部for循环也仅执行 n 次。这意味着算法的时间复杂度为 O(n)

答案 4 :(得分:0)

关键是两个初始解决方案都是二次方。它们涉及对父元素的每个的O(n)内部扫描(导致O(n ** 2))。

快速解决方案最初似乎遭受同样的命运,因为显而易见,它包含一个循环。但是内部的while循环不会不会完全扫描每个“叶子”。看一下“青蛙”的初始化位置,您会注意到while循环有效地为每个叶子保留了它的终止位置。

答案 5 :(得分:0)

这是我考虑数字级数总和的 100% 解决方案。

def solution(X, A):
covered = [False] * (X+1)
n = len(A)
Sx = ((1+X)*X)/2 # sum of the numeric progression
for i in range(n):
    if(not covered[A[i]]):
        Sx -= A[i]
    covered[A[i]] = True
    if (Sx==0):
        return i
return -1

答案 6 :(得分:0)

@sphoenix 的优化方案,不需要比较两个set,不太好。

def solution(X, A):
    found = set()
    for pos, i in enumerate(A, 0):
        if i <= X:
            found.add(i)
            if len(found) == X:
                return pos
    return -1

还有一种更优化的二进制数组解决方案

def solution(X, A):
    steps, leaves = X, [False] * X
    for minute, leaf in enumerate(A, 0):
        if not leaves[leaf - 1]:
            leaves[leaf - 1] = True
            steps -= 1
            if 0 == steps:
                return minute
    return -1

最后一个更好,资源更少。与二进制列表(内存和 CPU)相比,set 消耗更多资源。

答案 7 :(得分:0)

def solution(X, A):
    
    # if there are not enough items in the list
    if X > len(A):
        return -1
    # else check all items
    else:
        d = {}
        for i, leaf in enumerate(A):
            d[leaf] = i
            if len(d) == X:
                return i   

    # if all else fails
    return -1