【问题标题】:Python: Output all ranges that sum up to target sumPython:输出总和为目标总和的所有范围
【发布时间】:2021-08-28 00:49:28
【问题描述】:

问题:

给定由非零、非负整数 1 到 K 组成的 K,输出总和等于 K 的所有范围/区间。

例如,如果 K 等于 6,则输出应为 [[1,3], [6,6]]。对于[1,3],1+2+3 = 6,对于[6,6],6 = 6。

我的解决方案

下面是我的解决方案,但我认为时间复杂度是 O(N2)。有没有更有效的方法来做到这一点?

def targetSum(k):
  nums = list(range(1,k+1))
  res = []
  for end in range(len(nums)):
    start = 0
    while start <= end:
      sumhere = sum(nums[start:end+1])
      if sumhere == k:
        res.append([nums[start], nums[end]])
      start+=1
  return res

targetSum(6)

【问题讨论】:

    标签: python arrays algorithm data-structures


    【解决方案1】:

    您可以在O(sqrt(K)) 时间内使用一点数学来解决这个问题。

    范围和是arithmetic progression的和,差为1,所以我们可以写公式

    K = n/2 * (2*a + n - 1) or
    2 * K = n * (2*a + n - 1) 
    

    n 是范围大小,a 是起始值

    因此我们将2*K 的所有可能因式分解为两个除数2*K = p * q ,并求解简单系统

    n = p
    2*a + n - 1 = q
    

    2*a + p - 1 = q
    a  = (q + 1 - p) / 2
    

    请注意,对于具有不同奇数/均匀性/奇偶性的除数存在解决方案(这里哪个术语更好?)(否则a 不是整数),并且q 必须大于@ 987654332@(得到肯定的a) - 这个事实允许更早地停止循环。

    K=6 的示例:

    2K = 12
    1 * 12 :  n = 1, a = 6   (range 6..6)
    2 * 6:   no solution (both even) 
    3 * 4:    n = 3, a = 1  (range 1..3)
    

    简单的实现(对于非常大的值,它比@hilberts_drinking_problem 实现慢一点(两倍))

    def findranges(k):
        n = 1
        kk = 2 * k
        res = []
        while n * n < kk:
            if kk % n == 0:
                q = kk // n
                if (q ^ n) & 1: //compare parity using the least significant bit
                    a = (q + 1 - n) // 2
                    res.append([a, a + n - 1])
            n += 1
        return res
    
    print(findranges(60))
    
      
    

    【讨论】:

      【解决方案2】:

      您可以在 O(K) 中使用 sliding window concepttwo pointers approach 你可以说。

      sumhere = sum(nums[start:end+1]) 步骤,您重复计算总和,这导致您的 O(K^2)。而是继续向右移动end 并继续将其添加到总和中。如果 sum 等于 K,则加到结果中。如果 sum > K,则开始向右移动 start 并在 sum > K 时继续从总和中减少它。如果 sum 等于 K,则添加到结果。重复此操作,直到处理完该范围内的所有数字。

      可能是也可能不是一些数学技巧可以在这里提供帮助。如果我能想出更好的方法,我会告诉你的。

      【讨论】:

      • 你有代码 sn-p 或实现来证明这一点吗?
      • 我给出的两个链接也有代码。这些概念很常见,很多材料都可以在网上找到。我建议你自己编码。您的帖子中已经包含了大部分代码。你只需要稍微调整一下。这就是我们学习的方式。希望答案有所帮助。
      猜你喜欢
      • 1970-01-01
      • 2023-01-26
      • 2015-06-15
      • 1970-01-01
      • 2016-10-19
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      相关资源
      最近更新 更多