Testdome for Python的两次总和测试 - 如何通过性能测试?

时间:2018-03-12 15:53:36

标签: python algorithm performance

我正在编写一个函数,给定一个numbers和一个target_sum的列表,返回基于零的索引任何两个不同的元素,其总和等于目标总和。如果没有这样的元素,函数应该返回(-1,-1)。

这是我提出的解决方案:

class TwoSum:

    @staticmethod
    def find_two_sum(numbers, target_sum):
        """
        :param numbers: (list of ints) The list of numbers.
        :param target_sum: (int) The required target sum.
        :returns: (a tuple of 2 ints) The indices of the two elements whose sum is equal to target_sum
        """
        numbers = list(sorted(numbers))  # added after the update
        # to make sure numbers are always sorted        
        lo_index = 0
        hi_index = len(numbers) - 1
        while lo_index < hi_index:
            pair_sum = numbers[lo_index] + numbers[hi_index]
            if pair_sum < target_sum:
                lo_index += 1
            elif pair_sum > target_sum:
                hi_index -= 1
            else:
                return (lo_index, hi_index)
        return (-1, -1)


print(TwoSum.find_two_sum([1, 3, 5, 7, 9], 12))  # I assume the list is already sorted

我在testdome发现了这个挑战,我想知道为什么这个代码在最后一次测试时失败了Performance test with a large number of elements: Wrong answer。我目前正在进行招聘测试,并认为这个解决方案已经足够好了。

更新

我想我提出的解决方案完全没问题。我只想在我的机器上添加执行时间,以获得目前为止给出的答案。我在评论中提到了我的函数numbers = list(sorted(numbers))

>>> timeit.timeit(lambda: find_two_jdehesa([1, 3, 5, 7, 9], 12))
3.0298462831085544
>>> timeit.timeit(lambda: find_two_delirious_lettuce([1, 3, 5, 7, 9], 12))
1.6323729552793793
>>> timeit.timeit(lambda: find_two_op([1, 3, 5, 7, 9], 12))
1.23889097157587

更新2:

import random

>>> timeit.timeit(lambda: find_two_jdehesa(random.sample(range(1, 1000), 500), random.randint(1, 999)), number=10000)
8.197637722340914
>>> timeit.timeit(lambda: find_two_delirious_lettuce(random.sample(range(1, 1000), 500), random.randint(1, 999)), number=10000)
5.175919267269819
>>> timeit.timeit(lambda: find_two_op(random.sample(range(1, 1000), 500), random.randint(1, 999)), number=10000)
6.3352265931093825

4 个答案:

答案 0 :(得分:4)

这是我对LeetCode的两个求和问题的解决方案(修改后适合你的类),但它应该在这里工作:

class TwoSum:
    @staticmethod
    def find_two_sum(numbers, target_sum):
        seen = {}
        for i, num in enumerate(numbers):
            try:
                return (seen[num], i)
            except KeyError:
                seen[target_sum - num] = i
        return (-1, -1)

答案 1 :(得分:1)

您的解决方案基本上没问题,但您没有考虑输入可能没有排序,因此您必须先对其进行排序并跟踪排序的索引,以便稍后返回正确的索引值:< / p>

class TwoSum:

    @staticmethod
    def find_two_sum(numbers, target_sum):
        """
        :param numbers: (list of ints) The list of numbers.
        :param target_sum: (int) The required target sum.
        :returns: (a tuple of 2 ints) The indices of the two elements whose sum is equal to target_sum
        """
        # Sort numbers and get sorted indices
        numbers, idx = map(list, zip(*sorted(zip(numbers, range(len(numbers))))))
        if len(numbers) < 2:
            return (-1, -1)
        i = 0
        j = len(numbers) - 1
        while i < j:
            s = numbers[i] + numbers[j]
            if s == target_sum:
                # Return indices from the unsorted list
                return (idx[i], idx[j])
            elif s < target_sum:
                i += 1
            elif s > target_sum:
                j -= 1
        return (-1, -1)

print(TwoSum.find_two_sum([1, 3, 5, 7, 9], 12))

答案 2 :(得分:0)

我在测试圆顶上进行测试。它满足大数据以外的所有要求

def find_two_sum(numbers, target_sum):
"""
:param numbers: (list of ints) The list of numbers.
:param target_sum: (int) The required target sum.
:returns: (a tuple of 2 ints) The indices of the two elements whose sum is equal to target_sum
"""
i = 0
j = len(numbers) - 1
while i < j:
    if numbers[i] + numbers[j] == target_sum:
        return (i, j)
    if numbers[i] + numbers[j] < target_sum:
        i += 1

    else:
        j -= 1

return None 

print(find_two_sum([3,1,5,7,7,5,9],10))

答案 3 :(得分:0)

根据testDome提供的提示:

提示1:嵌套的for循环可以遍历列表并以O(N ^ 2)时间计算总和。

提示2:可以使用dict来存储预先计算的值,这可能允许具有O(N)复杂度的解决方案。

我有以下解决方案:

def find_two_sum(numbers, target_sum):
    taken = {}
    for i, num in enumerate(numbers):
        diff = target_sum - num
        if diff in taken:
            return i, taken[diff]
        taken[num] = i

my_list = [3, 1, 5, 7, 5, 9]
print(find_two_sum(my_list, 10))

我得到以下结果:

Run OK
(3, 0) 
Your score is 100%, perfect!