《剑指 Offer (第 2 版)》第 57-2 题:和为 S 的连续正数序列

第 57-2 题:和为 S 的连续正数序列

传送门:AcWing:和为 S 的连续正数序列

输入一个正数 s ,打印出所有和为 s 的连续正数序列(至少含有两个数)。

例如输入15,由于 1+2+3+4+5=4+5+6=7+8=15,所以结果打印出 3 个连续序列 1~54~67~8

样例:

输入:15

输出:[[1,2,3,4,5],[4,5,6],[7,8]]

思路:双指针,因为是有序数组,所以可以使用二分法。

设定两个指针,一个指向第一个数,一个指向最后一个数,在此之前需要设定第一个数和最后一个数的值,由于是正数序列,所以可以把第一个数设为 1,最后一个数为 2,因为是要求是连续正数序列,最后不可能和第一个数重合。下一步就是不断改变第一个数和最后一个数的值,如果从第一个数到最后一个数的和刚好是要求的和,那么把所有的数都添加到一个序列中;如果大于要求的和,则说明从第一个数到最后一个数之间的范围太大,因此减小范围,需要把第一个数的值加 1,同时把当前和减去原来的第一个数的值;如果小于要求的和,说明范围太小,因此把最后一个数加 1,同时把当前的和加上改变之后的最后一个数的值。这样,不断修改第一个数和最后一个数的值,就能确定所有连续正数序列的和等于 S 的序列了。

等差数列求和公式,首项加末项的和乘以个数除以 2,即 {\rm sum} = \cfrac {(a + b)\times n }{2}

注意:右边界问题,使用一个特例,例如 3 就可以考虑清楚了。

Python 代码:

class Solution(object):
    def findContinuousSequence(self, sum):
        """
        :type sum: int
        :rtype: List[List[int]]
        """

        res = []

        left = 1
        right = 2

        # sum = 3 的时候,右边界最多到 2
        half = sum // 2 + 1
        while left < right <= half:
            cur_sum = (left + right) * (right - left + 1) // 2
            if cur_sum == sum:
                res.append([i for i in range(left, right + 1)])
                right += 1
            elif cur_sum < sum:
                right += 1
            else:
                assert cur_sum > sum
                left += 1
        return res


if __name__ == '__main__':
    sum = 15
    solution = Solution()
    result = solution.findContinuousSequence(sum)
    print(result)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容