题目:
给出一个正整数N和长度L,找出一段长度大于等于L的连续非负整数,他们的和恰好为N。答案可能有多个,我我们需要找出长度最小的那个。
例如 N = 18 L = 2:
5 + 6 + 7 = 18
3 + 4 + 5 + 6 = 18
都是满足要求的,但是我们输出更短的 5 6 7
综合网上给出的参考答案,有两种相对简单,用python语言重写一下。
方法一:从数列的角度出发
解题思路:等差数列求和。
该题可理解为“一段长度大于等于L的等差数列之和等于N”的过程。
S =L(a1+an) / 2
= L(a1+a1+(L-1)d) / 2
= L(2a1+L-1) / 2= N
得:a1= (2N-L^2+L) / (2L)因此只需要判断求得的a1是否为正整数即可
1 N = eval(input('请输入一个正整数:')) 2 L = eval(input('请输入长度:')) 3 while True: 4 a1 = (2 * N - L * L + L) / (2 * L) 5 if (2*N-L**2+L)%(2*L) == 0 and a1 >0: #确保a1为正整数 6 an = a1 + L 7 res = [i for i in range(int(a1), int(an))] 8 print(res) 9 break 10 else: 11 L += 1 12 continue
方法二: 从中位数的角度出发。
解题思路:所求的序列的个数要么是偶数,要么是单数。那么,其中位数要么是整数,要么是小数部分为5的小数。例如【5,6,7】的中位数就等于(5+6+7)/3 = 6,而【6,7,8,9】的中位数等于(6+7+8+9)/4=7.5。
所以,情况可以分为两种,第一:序列长度为偶数的情况,此时N=中位数*L;第二:序列长度为奇数的情况,此时,N=xx.5 * L。
1 import math 2 N = eval(input('请输入一个正整数:')) 3 L = eval(input('请输入长度:')) 4 5 while True: 6 if L % 2 ==1 and N % L == 0: #如果序列长度为奇数且中位数为整数 7 middle = N / L #中位数 8 if middle-(L-1)/2 >0: #必须确保序列的首位大于0 9 list = [i for i in range(int(middle-(L-1)/2), int(middle+(L-1)/2)+1)] 10 print(list) 11 break 12 elif L % 2 ==0 and N/L - math.floor(N/L) == 0.5: #如果序列长度为偶数,且中位数为xx.5 13 middle = N / L #中位数 14 if math.floor(middle-L/2)>0: #必须确保序列的首位大于0 15 list = [i for i in range(math.ceil(middle-L/2), math.floor(middle+L/2)+1)] 16 print(list) 17 break 18 else: 19 L += 1 20 continue