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

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

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

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

例如输入,由于 ,所以结果打印出 个连续序列 、 和 。

样例:

输入:

输出:

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

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

等差数列求和公式,首项加末项的和乘以个数除以 ,即 。

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

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)

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