序列和-------一道大厂秋招笔试题

题目:

给出一个正整数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

 

posted @ 2020-03-28 22:33  牛公的跑奔  阅读(471)  评论(0编辑  收藏  举报
总访问量:AmazingCounters.com