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

面试题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]

实现效果


find_continuous_sequence_result.png

以上就是 《和为s的连续正数序列》 的解题过程及实现。主要涉及的思路也是数学方法等差数列求和,不过这里引入了一个概念,就是首末两项的间隔。简化问题为求得首项的情况下,根据间隔得出末项。


欢迎关注微信公众号《书所集录》
欢迎关注微信公众号《书所集录》

你可能感兴趣的:(LeetCode 面试题57 - II. 和为s的连续正数序列)