Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
一圈?python_Python - Fatal编程技术网

一圈?python

一圈?python,python,Python,所以我写了这个函数,它是给定可能数的,它必须找到组成给定数的可能数中的两个数。然而,我仍在学习Python(一种非常出色的语言),因此我只能使用有限的函数集 我创建了这个函数: def sumPair(theList, n): theList = charCount(theList) #charCount is a function i made to convert the list into a dictionary for i in theList: fo

所以我写了这个函数,它是给定可能数的,它必须找到组成给定数的可能数中的两个数。然而,我仍在学习Python(一种非常出色的语言),因此我只能使用有限的函数集

我创建了这个函数:

def sumPair(theList, n):

    theList = charCount(theList) #charCount is a function i made to convert the list into a dictionary
    for i in theList:
        for a,b in theList.iteritems():
            print a,b
            if a + i == n:
                if theList[b] > 1:
                    return [i, b]
                if a != i:
                    return [i, b]
        return "[]"
print sumPair([6,3,6,8,3,2,8,3,2], 11)   
就像我说的,它会找到两个和给定数字相加的数字
charCount
是我编写的一个函数,它将数组添加到字典中

在这个程序中,我确保在所加的数字相同的情况下,该值大于1。有时,如果它检查10的和,你给它一个5的数字,它只会将5加到它自己,然后返回10。这就是为什么
如果列表[b]>1:

我为什么在这里?我的教练对两个循环不满意。我花了5个小时排除故障,结果一无所获。我需要把这个程序转换成一个单循环程序


我花了一整天在这上面,我不是想让你做作业,我只是真的被卡住了,我需要你的帮助。我听说我应该检查是否存在一个密钥来完成这项任务。

教员可能不满意您的算法花费的时间比必须花费的时间更长。试试这个:

for each element x in theList
  if there exists an element y in theList such that x+y = n, you have a match
您需要快速进行“if exists”测试,这就是您使用字典的目的。一个循环将建立此词典,第二个循环将搜索整个词典。与O(n^2)时间相比,这需要线性时间

你关于5点与自身匹配的观点是正确的。您希望使用称为multiset或bag的数据结构。阅读相关内容,然后以以下方式实现代码:

for each element x in theList
  if there exists an element y in theList such that x+y == n:
    if x != y or (x == y and x occurs more than once):
      you have a match
祝你好运

编辑,因为有太多次优解,这里是简单的线性解(它是线性的,因为列表中有两个循环,但是循环一个接一个地出现。因此,2*n次迭代,O(n)。它非常快

#!/usr/bin/python2.6

from collections import defaultdict

def sum_list(l, n):
  count = defaultdict(lambda: 0)

  for x in l:      # O(n)
    count[x] += 1  # This can be done in constant time O(1)

  for x in l:      # O(n)
    y = n - x
    if count[y] > 0 and (x != y or count[y] > 1): # O(1)
      return x, y
我的评论:

  • 如果将列表转换为字典,请将名称从
    theList
    更改为其他名称。如果有一个名为
    theList
    的变量保存字典,则会造成混淆

  • 如果这两个数字总是相邻,您可以尝试编写一个循环,将索引变量
    i
    设置为0,然后递增
    i
    ,检查
    list[i]+list[i+1]
    是否等于所需的数字

  • 如果这两个数字可能不相邻,那么就比较棘手了。最明显的方法是使用两个循环:一个循环依次查看每个数字,另一个循环查看下面的数字,看看它们是否等于目标值。如果这两个数字不必相邻,并且讲师希望您只使用一个循环,然后,您需要使用一些东西来保存列表值(比如字典),或者可能使用“隐式循环”

我所说的“隐式循环”是什么意思?Python在中提供了一个操作符,
,它将告诉您对象是否在Python列表中。它通过循环列表来工作,但您不编写循环;循环是在Python内部为您完成的

因此,您可以这样做:依次查看每个数字。从目标值中减去数字,然后在
中使用
,查看计算值是否在列表的其余部分。要搜索列表的其余部分并跳过当前值,请使用“列表切片”.如果你还没有学会切片,你的指导老师可能不是在寻找列表切片的答案

下面是一个示例。如果将
i
设置为0,并且查看列表中的第一个条目,则值为6。目标值为11。因此计算值为(11-6)或者5.然后检查列表中是否有
computed\u值
。要仅查看列表的其余部分,可以使用切片,然后在列表中有
computed\u值[1:
。如果有索引变量
i
,则类似于
computed\u值=11-列表[i]
然后检查列表[i:]
中的
计算值

  • 不要忘记,可以使用
    for
    循环来创建从0到列表长度的索引,并使用索引索引到列表中。在Python中,通常最好在lst:
中使用
for x,它将
x
设置为列表中的连续对象,但有时在使用时会遇到问题ul对xrange中的i使用
(len(lst)):
,然后使用
lst[i]
lst[i+1]
lst[i:
或其他任何东西

  • 使用老师想要的任何编码样式。如果老师想要像“theList”这样的“camelCase”名称,那么就这样做。但是Python的常用样式称为“pep8”,并且该样式中的变量名是小写加下划线的,如“theu list”


  • 纯python-未使用库:

    def combinations(lst):
        l = lst[:] # copy of source list
        while len(l) > 1:
            a = l.pop(0)
            for b in l:
               yield a,b
    
    def first_pair(iterator):
        for i in iterator:
           # just return first element
           return i
    
    def sum_pair(lst, sum_val):
        return first_pair((a,b) for a,b in combinations(lst) if (a+b) == sum_val)
    
    print sum_pair([6,3,6,8,3,2,8,3,2], 11)
    # result (3,8)
    
    使用itertools:

    from itertools import combinations, islice
    
    def sum_pair(lst, sum_val):
        return list(islice(((a,b)
            for a,b in combinations(lst, 2) if (a+b) == sum_val), 0, 1))
    
    print sum_pair([6,3,6,8,3,2,8,3,2], 11)
    # result [(3,8)]
    

    思考这个问题总是有帮助的,我应该如何用手,用铅笔和纸,甚至只看纸上的一行数字。然而,更好的解决方案一开始可能看起来过于复杂,它们的优势一开始可能并不那么明显——看(他的答案是我个人的赢家,见下文)

    首先,您需要将一个数字与所有其他数字进行比较。然后将第二个数字与其他数字进行比较,等等。当使用朴素方法时,在使用单个进程时,无法避免两个嵌套循环。然后时间复杂度始终为O(n^2)其中,n是序列的长度。事实上,一些循环可能隐藏在操作中,如
    中的
    list.index()
    ,这在原则上不会使解决方案变得更好

    想象一下数字的笛卡尔积——它由数对组成。有n^2对这样的数对,但大约有一半是关于加法运算的可换性的,n的
    for each first element in theList:
        for each second element in the rest of theList from the checked one on:
            if the first and the second elements give the solution:
                report the result
                possibly early break if only the first should be reported
    
    def sumPair(theList, n):
        for index, e in enumerate(theList):     # to know the index for the slicing below
            complement = n - e                  # we are searching for the complement
            if complement in theList[index+1:]: # only the rest is searched
                return e, complement            
    
    print sumPair([6,3,6,8,3,2,8,3,2], 11)
    
    def sumPair2(theList, n):
        for ind, e in enumerate(theList):
            try:
                theList.index(n - e, ind + 1)
                return e, n - e
            except ValueError:
                pass
    
    import timeit
    
    def sumPair(theList, n):
        for index, e in enumerate(theList):
            if n - e in theList[index+1:]:
                return e, n - e
    
    def sumPair2(theList, n):
        for ind, e in enumerate(theList):
            try:
                theList.index(n - e, ind + 1)
                return e, n - e
            except ValueError:
                pass
    
    def sumPair_gnibbler(theList, n):
        # If n is even, check whether n/2 occurs twice or more in theList
        if n%2 == 0 and theList.count(n/2) > 1:
            return n/2, n/2
    
        theSet = set(theList)
        for e in theSet:
            if n - e in theSet:
                return e, n - e
    
    theList = [6,3,6,8,3,2,8,3,2]
    
    n = 11
    print '---------------------', n
    print sumPair(theList, n), 
    print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 1000)
    
    print sumPair2(theList, n), 
    print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 1000)
    
    print sumPair_gnibbler(theList, n),
    print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 1000)
    
    n = 1
    print '---------------------', n
    print sumPair(theList, n), 
    print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 1000)
    
    print sumPair2(theList, n), 
    print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 1000)
    
    print sumPair_gnibbler(theList, n),
    print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 1000)
    
    --------------------- 11
    (3, 8) 0.00180958639191
    (3, 8) 0.00594907526295
    (8, 3) 0.00124991060067
    --------------------- 1
    None 0.00502748219333
    None 0.026334041968
    None 0.00150958864789
    
    theList = range(10000)
    
    n = 11
    print '---------------------', n
    print sumPair(theList, n), 
    print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 100)
    
    print sumPair2(theList, n), 
    print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 100)
    
    print sumPair_gnibbler(theList, n),
    print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 100)
    
    n = 3000
    print '---------------------', n
    print sumPair(theList, n), 
    print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 100)
    
    print sumPair2(theList, n), 
    print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 100)
    
    print sumPair_gnibbler(theList, n),
    print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 100)
    
    n = 30000
    print '---------------------', n
    print sumPair(theList, n), 
    print timeit.timeit('sumPair(theList, n)', 'from __main__ import sumPair, theList, n', number = 100)
    
    print sumPair2(theList, n), 
    print timeit.timeit('sumPair2(theList, n)', 'from __main__ import sumPair2, theList, n', number = 100)
    
    print sumPair_gnibbler(theList, n),
    print timeit.timeit('sumPair_gnibbler(theList, n)', 'from __main__ import sumPair_gnibbler, theList, n', number = 100)
    
    --------------------- 11
    (0, 11) 0.00840137682165
    (0, 11) 0.00015695881967
    (0, 11) 0.089894683992
    --------------------- 3000
    (0, 3000) 0.0166750746034
    (0, 3000) 0.00966040735374
    (0, 3000) 0.12532849753
    --------------------- 30000
    None 180.328006493
    None 163.651082944
    None 0.204691100723
    
    def sumPair(theList, n):
        # If n is even, check whether n/2 occurs twice or more in theList
        if n%2 == 0 and theList.count(n/2) > 1:
            return [n/2, n/2]
    
        theSet = set(theList)
        for i in theSet:
            if n-i in theSet:
                return [i, n-i]
        return []
    
    def get_sum_pairs(sum = None, list_of_numbers = None):
        assert sum != None and list_of_numbers != None
        list_of_numbers = sorted(list_of_numbers) # sort the list of numbers O(n log n)        
        for index, number in enumerate(list_of_numbers): # search for each number that is less than the sum O(n)
            if number < sum: # if number greater then sum, theres nothing we can do.
                for index, number_1 in enumerate(list_of_numbers[(index + 1):]): # search the second list, this isn't exactly O(n) since its incremented being incremented
                    if number + number_1 == sum: # found a solution.
                        return [(number, number_1)]
                    if (number_1 > sum) or (number + number_1 > sum): # if number greater then sum, theres nothing we can do.
                        break                                       # if the addition of two sorted numbers is greater then sum, then theres no need to keep searching since the rest will also be greater, since their sorted.
            else:
                break
        return [()]
    
    assert all([get_sum_pairs(**test[0]) == test[1] for test in
         [({'list_of_numbers':[6,3,6,8,3,2,8,3,2], 'sum':11}, [(3, 8)]),
         ({'list_of_numbers':[1,2,3,4,1,2], 'sum':1}, [()]),
         ({'list_of_numbers':[1,2,3,1,23,1,23,123], 'sum':124}, [(1, 123)]),
         ({'list_of_numbers':[1,2,3,12,3,2,1,23,4,1,23,4,5,12332], 'sum':14}, [(2, 12)]),
         ({'list_of_numbers':[-1,2,-2, -3, 1, 2, 3, 2, -1.3], 'sum':1}, [(-1, 2)])
         ] ])
    
    def sumpairs(numbers, n):
        numbers = [None] + numbers + [None] * (n-len(numbers))
        for k in range(len(numbers)):
            a = numbers[k]
            if a is None or a==k: continue
            if numbers[n-a]==n-a:
                return a, n-a
            numbers[k] = None
            while numbers[a] != a and a is not None:
                b = n-a
                if numbers[a] is None:
                    numbers[a] = a
                    break
                if numbers[b]==b:
                    return a, n-a
                numbers[a], a = a, numbers[a]
    
    print(sumpairs([6,3,6,8,3,2,8,3,2], 16))
    print(sumpairs([6,3,6,8,3,2,8,3,2], 11))
    print(sumpairs([6,3,5,8,3,2,8,3,2], 10))
    print(sumpairs([6,3,5,8,3,2,8,3,2], 5))
    print(sumpairs([6,3,5,8,3,2,8,3,2], 12)) # This should fail.
    
    def sumpairs(numbers, n):
        numbers = sorted(numbers)
        low = 0
        while low < len(numbers)-1:
            t = numbers[low] + numbers[-1]
            if t > n:
                numbers.pop(-1)
            elif t < n:
                low += 1
            else:
                return numbers[low], numbers[-1]
    
    print(sumpairs([6,3,6,8,3,2,8,3,2], 16))
    print(sumpairs([6,3,6,8,3,2,8,3,2], 11))
    print(sumpairs([6,3,5,8,3,2,8,3,2], 10))
    print(sumpairs([6,3,5,8,3,2,8,3,2], 5))
    print(sumpairs([6,3,5,8,3,2,8,3,2], 12)) # This should fail.