面试题57 - II. 和为s的连续正数序列

题目描述:
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

示例 1:

输入:target = 9
输出:[[2,3,4],[4,5]]

示例 2:

输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]

限制:

1 <= target <= 10^5

解题思路1:

通过遍历来找到最优的组合,但这样时间容易超出范围


代码1:

class Solution(object):
    def findContinuousSequence(self, target):
            a = []
            ret = []
            for i in range(1, target+1):
                a.append(i)

            number = target-1
            while number >= 2:
                for i in range(0, int(target/2+1)):
                    if sum(a[i:i+number]) == target:
                        ret.append(a[i: i+number])
                number -= 1
            return ret

s = Solution()
target = 9
print(s.findContinuousSequence(target))

以下方法来自博客:LeetCode | 面试题 57 - Ⅱ. 和为s的连续正数序列【Python


解题思路2:

i 指针表示窗口左边界,j 指针表示窗口右边界。
当 sum < target 时,j 指针右移。
当 sum > target 时,i 指针左移。
当 sum = target 时,窗口内的数组加入 res,i 指针右移。
注意窗口的 range 是左闭右开 [ )

代码2: 时间复杂度O(n)

class Solution:
    def findContinuousSequence(self, target):
        i, j = 1, 1
        sum = 0
        res = []

        while i <= target // 2:
            if sum < target:
                sum += j
                j += 1
            elif sum > target:
                sum -= i
                i += 1
            else:
                arr = list(range(i, j))
                res.append(arr)
                sum -= i
                i += 1

        return res

s = Solution()
target = 9
print(s.findContinuousSequence(target))

解题思路3:

求根公式

可以看出是等差数列,用求和公式:
               S n = n 2 ( a + a n ) S_{n}=\frac{n}{2}\left(a+a_{n}\right) Sn=2n(a+an)

设 x 为首项,y 为末项,则 y-x+1 为项数。设和为 target:
               target ⁡ = ( x + y ) ∗ ( y − x + 1 ) 2 \operatorname{target}=\frac{(x+y) *(y-x+1)}{2} target=2(x+y)(yx+1)

将上式展开:       x 2 − x − y 2 − y + 2 ∗ x^{2}-x-y^{2}-y+2 * x2xy2y+2 target = 0 =0 =0

根据求根公式:       x 1 , 2 = ∂ g ( x ) − b ± b 2 − 4 a c 2 a x_{1,2}=\partial g(x)-b \pm \sqrt{b^{2}-4 a c} 2 a x1,2=g(x)b±b24ac 2a
去掉负数根,就能得到下式:
           x = y 2 + y − 2 ∗  target  + 1 4 − 1 2 x=\sqrt{y^{2}+y-2 * \text { target }+\frac{1}{4}}-\frac{1}{2} x=y2+y2 target +41 21


代码3: 时间复杂度O(n)

class Solution:
    def findContinuousSequence(self, target):
        res = []
        
        for y in range(1, target // 2 + 2):  # range:左闭右开
            x = (1/4 + y**2 + y - 2*target) ** (1/2) + 0.5
            if type(x) != complex and x - int(x) == 0:  # x can't be complex and x must be int
                res.append(list(range(int(x), y + 1)))

        return res

s = Solution()
target = 9
print(s.findContinuousSequence(target))

解题思路4:

间隔法

根据上述的求根公式,将 i = y - x 代入,得到: target = ( 2 x + i ) ∗ ( i + 1 ) 2 =\frac{(2 x+i) *(i+1)}{2} =2(2x+i)(i+1)

进一步化简,得到:       target = x ( i + 1 ) + i ( i + 1 ) 2 =x(i+1)+\frac{i(i+1)}{2} =x(i+1)+2i(i+1)

最终得到:              x = target ⁡ − i ( i + 1 ) 2 i + 1 x=\frac{\operatorname{target}-\frac{i(i+1)}{2}}{i+1} x=i+1target2i(i+1)

于是,得到两个条件:

  1. i(i+1)/2 要小于 target
  2. 分子必须可以整除分母

代码4:

class Solution:
    def findContinuousSequence(self, target):
        i, res = 1, []

        while i*(i+1)/2 < target:
            if not (target - i*(i+1)/2) % (i+1):
                x = int((target - i*(i+1)/2) // (i+1))
                res.append(list(range(x, x+i+1)))
            i += 1
        return res[::-1]

s = Solution()
target = 9
print(s.findContinuousSequence(target))

参考链接:

[1]. LeetCode | 面试题 57 - Ⅱ. 和为s的连续正数序列【Python】

题目来源: https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值