剑指offer:和为S的连续正数序列
题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
# -*- coding: utf-8 -*-
# @Time : 2019-10-16 14:32
# @Author : Jayce Wong
# @ProjectName : job
# @FileName : FindContinuousSequence.py
# @Blog : https://sysujayce.github.io/
# @Github : https://github.com/SysuJayce
class Solution:
"""
要找连续子数组使得子数组的和为一个定值,考虑双指针标记数组的起止位置。
具体来说,
1. 首先将左指针指向全局数组的起点,然后移动右指针直到满足约束;
2. 如果找到了一个满足约束的子数组,将结果保存起来之后,先将左右指针都往右移动。
因为我们需要找另一个子数组,就需要先让当前的右指针往右移动,
而因为右指针发生了移动,那么左指针也至少需要一次移动;
3. 移动左指针直到找到另一个满足约束的子数组,然后重复步骤2和3。
循环终止的条件可以是当右指针移动到了全局数组的终点,也可以是左指针超越了右指针。
因为这样说明以该右指针为终点的子数组不存在满足约束的。
"""
def FindContinuousSequence(self, tsum):
left = right = 1
res = []
while left <= right < tsum:
cur_sum = (left + right) * (right - left + 1) // 2
# 局部和大于约束,需要将左指针往右,减少元素个数
if cur_sum > tsum:
left += 1
# 局部和小于约束,需要将右指针往右,增加元素个数
elif cur_sum < tsum:
right += 1
else:
# 找到一个满足约束的子数组之后,将左右指针都往右移动,寻找下一个子数组
res.append(list(range(left, right + 1)))
right += 1
left += 1
return res
- 原文作者:Jayce
- 原文链接:https://sysujayce.github.io/posts/findcontinuoussequence/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。