面试题57 - II. 和为s的连续正数序列
题目来源:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/
题目
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
解题思路
- 思路:等差数列求和
- 这里额外添加一个概念,末项与首项的间隔
i
。利用间隔i
,当求得首项时,可根据间隔求得末项。 - 尝试推导公式:
等差数列求和公式:
其中这里 y
表示末项,x
表示首项。现在我们引入一个间隔的概念 i
,那么可得 ,将其代入上面的公式中:
上面的式子可简化成:
最后可得:
根据上面的公式就可以求得首项 x
,在这里 x 必须是正整数,则 ,且题目提出序列至少有两个数,那么 ,,将 两个限定条件代入式子中,可以得出限定条件 1:
同时,因为 x 必须是正整数,所以上面的式子中:
这里所求得的结果,必须是整数,这就是限定条件 2。具体实现可用取模来判断。
那么根据这两个条件,用代码进行实现。
代码实现
class Solution:
def findContinuousSequence(self, target: int) -> List[List[int]]:
# i 代表间隔,res 表示返回序列
i, res = 1, []
# 这里就是限定条件 1
while target - i * (i + 1) * 0.5 >= 2:
# 先取模,看是否能整除
mod = (target - i * (i + 1) * 0.5) % (i + 1)
# 如果能整除,表示相除得到的是整数,这里可求得 x
if not mod:
x = int((target - i * (i + 1) * 0.5) / (i + 1))
# 将 x 以及从 x 开始间隔 i 的所有数字添加到序列中
res.append(list(range(x, x+i+1)))
i += 1
# 因为上面的结果是从间隔小的情况开始搜索
# 题目中给出的答案是按照间隔较大的顺序返回
# 所以将返回列表进行调转
return res[::-1]
实现效果
以上就是 《和为s的连续正数序列》 的解题过程及实现。主要涉及的思路也是数学方法等差数列求和,不过这里引入了一个概念,就是首末两项的间隔。简化问题为求得首项的情况下,根据间隔得出末项。
欢迎关注微信公众号《书所集录》
欢迎关注微信公众号《书所集录》