因此,这是可能著名的 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/dealvero/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循环!应该很慢,但事实并非如此。
使用 set()
具有出色的性能def solution(X, A):
positions = set()
seconds = 0
for i in range(0, len(A)):
if A[i] not in positions:
positions.add(A[i])
seconds = i
if len(positions) == X:
return seconds
return -1
或者使用 dictionary
具有出色性能的另一种解决方案def solution(X, A):
positions = {}
count = 0
seconds = -1
for i in range(len(A)):
if A[i] not in positions:
positions[A[i]] = i
count += 1
if count == X:
seconds = i
break
return seconds
这是一个解决方案,您可以在其中获得 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
答案已经告诉过,但我将添加一个可选的解决方案,我认为可能会帮助您理解:
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
嵌套循环的数量并不能直接告诉你任何关于时间复杂度的信息。令 n 为输入数组的长度。 while 循环内部需要 average O(1) 时间,尽管其最坏情况时间复杂度为 O(n)。快速解决方案使用布尔数组leaves,其中如果存在叶子,则每个索引的值都为true,否则为false。整个算法中 while 循环内部的执行次数不超过 n 次。外部 for 循环也仅执行 n 次。这意味着该算法的时间复杂度为O(n)。
关键是你的两个初始解都是二次的。它们涉及对父元素的each进行 O(n) 内部扫描(导致 O(n**2))。
快速解决方案最初似乎遭受了同样的命运,因为很明显它包含一个循环中的一个循环。但是内部 while 循环并没有完全扫描每个“叶子”。看一下“frog”的初始化位置,您会注意到 while 循环有效地从每片叶子停止的位置开始。
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
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)。
def solution(X, A):
if (X > len(A)): # check for no answer simple
return -1
elif(X == 1): # check for single element
return 0
else:
std_set = {i for i in range(1,X+1)} # list of standard order
this_set = set(A) # set of unique element in list
if(sum(std_set) > sum(this_set)): # check for no answer complex
return -1
else:
for i in range(0, len(A) - 1):
if std_set:
if(A[i] in std_set):
std_set.remove(A[i]) # remove each element in standard set
if not std_set: # if all removed, return last filled position
return(i)
我想这段代码可能无法满足运行时的要求,但它是我能想到的最简单的
def solution(X, A):
from collections import OrderedDict as od
if sum(set(A))!=(X*(X+1))//2:
return -1
k=list(od.fromkeys(A).keys())[-1]
for x,y in enumerate(A):
if y==k:
return x
def solution(x, a):
# write your code in Python 3.6
# initialize all positions to zero
# i.e. if x = 2; x + 1 = 3
# x_positions = [0,1,2]
x_positions = [0] * (x + 1)
min_time = -1
for k in range(len(a)):
# since we are looking for min time, ensure that you only
# count the positions that matter
if a[k] <= x and x_positions[a[k]] == 0:
x_positions[a[k]] += 1
min_time = k
# ensure that all positions are available for the frog to jump
if sum(x_positions) == x:
return min_time
return -1
def solution(X, A):
positions = set()
for i in range(len(A)):
if A[i] not in positions:
positions.add(A[i])
if len(positions) == X:
return i
return -1
def solution(X, A):
s = set()
for i, leaf in enumerate(A):
s.add(leaf)
if len(s) == X:
return i
return -1