找到小于给定数字的三胞胎

时间:2018-03-31 20:01:40

标签: python algorithm sorting data-structures

我正在尝试解决以下问题:

  

给定n个整数nums和target的数组,找到数字   索引三元组i,j,k,其中0 <= i <1。 j&lt; k&lt;满足的   条件nums [i] + nums [j] + nums [k]&lt;目标

     

例如,给定nums = [-2,0,1,3]和target = 2.

     

返回2.因为有两个三元组,其总和小于2:

     

[ - 2,0,1] [-2,0,3]

我的算法:从列表中删除单个元素,设置target = target - number_1,搜索doublets,使number_1 + number _2&lt;目标 - number_1。问题解决了。

问题链接为https://leetcode.com/problems/3sum-smaller/description/

我的解决方案是:

    def threeSumSmaller(nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """

        nums = sorted(nums) 
        smaller = 0

        for i in range(len(nums)):

            # Create temp array excluding a number

            if i!=len(nums)-1:
                temp = nums[:i] + nums[i+1:]

            else:
                temp = nums[:len(nums)-1]


            # Sort the temp array and set new target to target - the excluded number

            l, r = 0, len(temp) -1 
            t = target - nums[i]

            while(l<r):

                if temp[l] + temp[r] >= t:

                    r = r - 1

                else:

                    smaller += 1

                    l = l + 1


        return smaller

我的解决方案失败了:

Input:
[1,1,-2]
1
Output:
3
Expected:
1

我不知道为什么会出现错误,因为我的解决方案通过了超过30个测试用例。

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

一个要点是,当您对第一行中的元素进行排序时,您也会丢失索引。这意味着,尽管找到了三元组,但您永远无法确定(i, j, k)是否满足条件1,因为(i, j, k)不是来自原始列表,而是来自新列表

此外:每次从数组中间采集元素时,数组的剩余部分也会被迭代(尽管以不规则的方式,它仍然从tmp中的第一个剩余元素开始) 。情况应该不是这样!我正在扩展细节:

该示例在列表上迭代3次(再次排序,因此您将丢失真正的i,j和k索引):

  • 第一次迭代(i = 0, tmp = [1, -2], t = 0)。 如果总和temp[l] + temp[r]l, r0, 1),则为-1。 它满足低于tsmaller会增加。
  • 第二次迭代将与第一次迭代类似,但使用i = 1。 它会再次增加。
  • 第三个也会增加,因为t = 3和总和现在是2

因此,您将对该值进行三次计数(尽管只能按索引的顺序形成一个元组),因为您正在迭代索引的排列而不是组合< / em>他们。所以这两件事你没有注意:

  • 排序时保留索引。
  • 确保仅以正向方式迭代索引。

更好地尝试:

def find(elements, upper_bound):
    result = 0
    for i in range(0, len(elements) - 2):
        upper_bound2 = upper_bound - elements[i]
        for j in range(i+1, len(elements) - 1):
            upper_bound3 = upper_bound2 - elements[j]
            for k in range(j+1, len(elements)):
                upper_bound4 = upper_bound3 - elements[k]
                if upper_bound4 > 0:
                    result += 1
    return result

答案 1 :(得分:1)

似乎你不止一次计算同一个三元组 ......

在循环的第一次迭代中,省略列表中的第一个1,然后按smaller增加1。然后,省略列表中的第二个1,再按smaller增加1。最后你省略了列表中的第三个元素-2,当然还要smaller增加1,因为 - 好吧 - 在所有这三个案例中你实际上都在考虑相同三元组{1,1,-2}

P.S。看起来你更关心正确性而不是表现。在这种情况下,请考虑维护一组解决方案三元组,以确保您不会计算两次相同的三元组。

答案 2 :(得分:1)

已经有了很好的答案,除此之外,如果您想检查算法结果,那么您可以获得这种内置功能的帮助:

import itertools

def find_(vector_,target):
    result=[]
    for i in itertools.combinations(vector_, r=3):
        if sum(i)<target:
            result.append(i)
    return result

输出:

print(find_([-2, 0, 1, 3],2)) 

输出:

[(-2, 0, 1), (-2, 0, 3)]

如果你只想算一下:

print(len(find_([-2, 0, 1, 3],2)))

输出:

2