阅读目录
题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
思路及Python实现
- 第一种方法:暴力求解,在连续的正数序列中,如果一个数比和的一半要大的话,例如:和为100,如果其中一个数是51,那么,不存在51和另一个连续的数和等于100的这个序列。因此,我们可以借助两个循环,来循环遍历所有和等于tsum的序列!(效率低)
暴力求解
class Solution:
def FindContinuousSequence(self, tsum):
res = []
for i in range(1, tsum // 2 + 1):
sum = 0
for j in range(i, tsum // 2 + 2):
sum += j
if sum == tsum:
res.append(list(range(i, j + 1)))
if sum > tsum:
break
return res
obj = Solution()
print(obj.FindContinuousSequence(100))
双指针 滑动窗口
- 利用一个双指针来实现一个滑动窗口,如下图:左侧指针small,右侧指针big;如果当前窗口内的和等于tsum,返回窗口内的所有数,并且移动窗口,窗口右侧向右移动一位或者左侧右移一位都行;
- 两枚指针之间的和,如果小于tsum的话,窗口的big指针向右移动一位,然后再加上指针移动后指向位置的值;如果大于tsum的话,两枚指针之间的和先减去当前指针指向的值,窗口的samll指针向右移动一位;循环终止条件是,窗口左侧,即(窗口左侧)序列的最小值大于tsum//2,即思路1中的不会有数大于和的一半
- 详细如下图解
class Solution:
def FindContinuousSequence(self, tsum):
if tsum == 1:
return []
small = 1
big = 2
mid = tsum // 2
cur_sum = big + small # 会不断更新当前序列的和
ret = []
while small <= mid:
if cur_sum == tsum:
ret.append(list(range(small, big + 1)))
big += 1 # 如果右侧窗口移动(先移动再加)
cur_sum += big # 不断更新和
elif cur_sum < tsum:
big += 1
cur_sum += big
else: # 如果左侧窗口移动(先减在移动)
cur_sum -= small
small += 1
return ret
obj = Solution()
print(obj.FindContinuousSequence(100))