输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
- 示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
限制:
1 <= target <= 10^5
题解
按照纯数学平均数的想法来做的,代码可能写的比较啰嗦。
- 设最多能有n个数加起来能等于target, 则n >= 2
- 以n >= 2为while循环条件,找出这n个数字的平均数,注意Python3使用
//
进行除法会得到向下取整的整数 - 这个是重点,由于序列每个数字都必须为正整数,所以n个数字中最小的数字必须大于或等于1.
根据第三点,可以轻易得出一个公式:
当n为偶数时:平均数 - n // 2 + 1 >= 1
举个例子,target=9, n=4的时候,平均数为2,所以4个数字必须是围绕2组成,并且大小均匀分布,由于n=4,导致数组有2种情况, 分别为: [0, 1, 2, 3]和[1, 2, 3, 4],当第二种情况的最小数字都小于1的时候,第一种情况必定也会小于1,所以此时的判断公式为平均数 - n // 2 + 1 >= 1
当n为奇数时:平均数 - n // 2 >= 1
此时比较简单,中位数就是平均数,所以左右均匀分配,只需要平均数 - n // 2 >= 1
即可。
最后是n = 2的时候,由于数字不能重复,只要n是偶数,那么绝对不可能有2个一样的数字组成这个target。如果n是奇数,则mid为向下取余的数字,必有 奇数target = mid+(mid+1)
class Solution:
def findContinuousSequence(self, target: int) -> List[List[int]]:
# 最终结果数组
result = []
# 初始化target
n = target
while n > 2:
mid = target // n
# 判断n是否为偶数
if n % 2 == 0:
if mid - n // 2 + 1 < 1:
# 如果此序列的最小值都小于1,则n-- 循环继续
n -= 1
continue
# 满足第一种情况
if sum(range(mid - n // 2, mid + n // 2)) == target:
result.append(list(range(mid - n // 2, mid + n // 2)))
# 满足第二种情况
elif sum(range(mid - n // 2 + 1, mid + n // 2 + 1)) == target:
result.append(list(range(mid - n // 2 + 1, mid + n // 2 + 1)))
else:
# 奇数时候,最小值小于1则继续循环
if mid - n // 2 < 1:
n -= 1
continue
if sum(range(mid - n // 2, mid + n // 2 + 1)) == target:
result.append(list(range(mid - n // 2, mid + n // 2 + 1)))
n -= 1
# 由于n >= 2
if target % 2 != 0:
mid = target // 2
result.append([mid, mid + 1])
return result
可以看到时间复杂度还是很多的,但是内存占用比较小,当然写的也比较啰嗦,慢慢刷吧!无套路太难了~