题目描述:
输入一个正整数 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)∗(y−x+1)
将上式展开: x 2 − x − y 2 − y + 2 ∗ x^{2}-x-y^{2}-y+2 * x2−x−y2−y+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±b2−4ac2a
去掉负数根,就能得到下式:
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+y−2∗ 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+1target−2i(i+1)
于是,得到两个条件:
- i(i+1)/2 要小于 target
- 分子必须可以整除分母
代码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