【问题标题】:Find Triplets smaller than a given number查找小于给定数字的三元组
【发布时间】:2018-03-31 20:01:39
【问题描述】:

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

给定一个由 n 个整数组成的数组 nums 和一个目标,找出其中的个数 索引三元组 i, j, k 满足 0

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

返回 2。因为有两个三元组之和小于 2:

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

我的算法:从列表中删除单个元素,设置 target = target - number_1,搜索使 number_1 + number _2

问题链接是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 多个测试用例。

感谢您的帮助。

【问题讨论】:

    标签: python algorithm sorting data-structures


    【解决方案1】:

    一个要点是,当您对第一行中的元素进行排序时,您也会丢失索引。这意味着,尽管找到了三元组,但您永远无法确定您的 (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

    因此,您将计算该值 3 次(尽管只能按索引顺序形成一个元组),因为您正在迭代索引的 排列 而不是 组合 其中。所以这两件事你没有在意:

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

    试试这样更好:

    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
    

    【讨论】:

      【解决方案2】:

      好像你不止一次数同一个三元组...

      在循环的第一次迭代中,省略列表中的第一个1,然后将smaller 增加1。然后您省略列表中的第二个1 并再次将smaller 增加1。最后你省略了列表中的第三个元素-2,当然smaller 增加了1,因为——嗯——在所有这三种情况下,你实际上都在考虑相同强> 三元组{1,1,-2}.

      附言似乎您更关心正确性而不是性能。在这种情况下,请考虑维护一组解决方案三元组,以确保您不会将同一个三元组计算两次。

      【讨论】:

      • 谢谢,但我认为那不正确。我是第一个排序.. -2 1 1 。并且 while 循环不应允许 l==r 情况。所以只考虑一个三元组。我的推理有什么问题......谢谢你的帮助
      • 请再检查一次....我说的不是“lsmaller 增加1 时,只需print 你找到的三元组。
      • @Yanix 是的,你说的是外部 for 循环..我的错
      【解决方案3】:

      已经有很好的答案了,除此之外,如果你想检查你的算法结果,那么你可以借助这个内置函数:

      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
      

      【讨论】:

        猜你喜欢
        • 2013-07-16
        • 2013-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-26
        • 2011-01-05
        • 2015-01-16
        相关资源
        最近更新 更多