因此,您将获得一个整数n,它对应于您拥有的宽松袜子的数量。然后给出一个袜子列表,其编号与其标签/颜色相对应。
例如,Sample输入:
9
10 20 20 10 10 30 50 10 20
输出:
3
在这种情况下,对是(10,10), (20,20), (10,10)
,因为每个袜子只能使用一次。
通过找到一对并将每个标记标记为-1
以表示已经位于一对中的袜子,我能够找到问题的解决方案。我的第一个解决方案似乎效率低下,因为循环遍历了包含-1
的值,所以我使用了上周我在课堂上学到的break and continue
。
这是我最近的解决方案:
import sys
n = int(input().strip())
c = [int(c_temp) for c_temp in input().strip().split(' ')]
matching = 0
pairFound = True
while pairFound:
pairFound = False
for i in range(len(c)):
if c[i] == -1:
continue
for j in range(i+1,len(c)):
if c[j] == -1:
continue
if c[i] == c[j] and c[i] != -1 and c[j] != -1:
pairFound=True
matching = matching + 1
c[i]=-1
c[j]=-1
if c[i] == -1:
break
print(matching)
我写的代码有多高效?
我并不是在寻找替代解决方案,我更感兴趣的是调整方法以使我现有的代码更好。
谢谢你们。
答案 0 :(得分:2)
您的代码效率不高,因为它的运行时间与元素数量(即socks)的平方成正比。您可以通过计算元素并获取(number_elements // 2)的总和来实现线性运行时。如果真的对运行时感兴趣,我建议使用模块集合中的Counter类。
答案 1 :(得分:2)
对于正在编程的第一步的人来说,从概念的角度来看,你的方法是完全可以的:
好消息是,您只需将第一个for
循环中每个项目的后续列表考虑在内,而不是遍历整个列表。
糟糕的是,可能会让您认为可以改进这一点,即标记已分配一对的袜子而不是从列表中删除它们。删除它们会缩短列表,从而减少完成任务所需的计算步骤。但是,在迭代它时从列表中删除项目是一个坏主意,所以你需要一些不同的东西。
此外,您可以省略封闭的while
循环,因为第一个for
循环无论如何都会在到达袜子序列结束时结束。当你到达结束时访问后续列表时,请注意IndexError
。
我怀疑你在课堂上已经涵盖了递归,但这是一种迭代更改列表并同时收集无法分配给一对的项目的有效方法(即< em>孤独的袜子)。
递归是关于从自身调用函数:
让socks
成为您的输入列表。您可以将其拆分为head
(第一个元素)和rest
(所有其他元素)。
socks = [10, 20, 10, 40]
head = socks[0] # Here, head will be 10
rest = socks[1:] # Here, rest will be [20, 10, 40]
首先,您需要在rest
中搜索等于head
的元素。找到后,您可以将其从rest
中删除,因为它无法配对多次:
for i, s in enumerate(rest):
if s == head:
match = rest.pop(i)
break
现在执行此步骤后,您知道找到了由head
和match
元素组成的对。并且,您的rest
列表已更改:您已删除匹配的部分:
[20, 40]
您可以重复这些步骤,直到rest
列表的长度为<= 1
,因此我们需要在此处再次运行,其中head
为20
且{{1将是rest
。迭代[40]
不会产生一对,我们应该按原样返回。
一旦你的迭代达到了rest
的长度rest
,你可以退出,因为你知道你必须找到所有对。
在代码中,这可能如下所示:
<= 1
此代码的输出类似于:
import random
def seek_pair(lst):
if len(lst) <= 1:
# Nothing to do if we cannot split list into head and rest
return lst
# Split list into head and rest
head, rest = lst[0], lst[1:]
# Iterate over rest and try to find a match
match = None
for i, s in enumerate(rest):
if s == head:
# We have found an element that equals our head
# Remove it from the list and store it in variable 'match'
match = rest.pop(i)
# Break the loop as we have found a match
break
if match:
# If there was a match in the 'rest' list, we can print it
print('Pair: ({:d}, {:d})'.format(head, match))
# And call the method 'seek_pair()' on the resulting 'rest'
# Note that here, the matching element has already been
# removed from the list 'rest'.
return seek_pair(rest) # RECURSION
else:
# If no match was found, we still need to search the 'rest'
# list for other matches.
# And, since 'head' did not match any other element, we append
# it to the beginning of our result list, which will hold all
# elements without matches (i.e. lonely socks).
return [head] + seek_pair(rest) # RECURSION
if __name__ == '__main__':
# Randomly generate an input list of desired length
n = 9
socks = [random.randint(1, 9) * 10 for _ in range(n)]
# Print the list
print('Socks: {:s}'.format(', '.join([str(s) for s in socks])))
# Call the function on the entire list and obtain its result,
# that should contain all lonely socks.
rest = seek_pair(socks)
# Print lonely socks
print('Rest: {:s}'.format(', '.join([str(s) for s in rest])))
答案 2 :(得分:0)
我的解决方案使用collections.Counter
>>> import collections
>>> c = [10, 20, 20, 10, 10, 30, 50, 10, 20]
>>> sum([int(i/2) for i in collections.Counter(c).values()])
>>> 3
如果想获得重复对的详细信息,请使用下面的代码。显示我们有4次出现10次,3次出现20次等等最多发生命令
>>> import collections
>>> c = [10, 20, 20, 10, 10, 30, 50, 10, 20]
>>> collections.Counter(c).most_common ()
>>> [(10, 4), (20, 3), (50, 1), (30, 1)]