试题 历届真题 杨辉三角形(python)

题目描述

方案一(暴力求解:40分)

解题思路与代码

暴力求解,一行接一行的模拟并判断,直到找到对应的数并打印结果。
解题的代码如下:

n = int(input())

a1 = [1]
a2 = [1,1]
count = 0
flag = 1
while(flag):
    # 先判断第一个
    # print(a1)
    for i in range(len(a1)):
        count +=1
        if a1[i]==n:
            flag = 0
            break
    
    # 更新a1、a2
    tmp = [1 for i in range(len(a2)+1)]
    for i in range(1,len(a2)):
        tmp[i] = a2[i-1]+a2[i]
    
    a1 = a2
    a2 = tmp

print(count)

提交结果

结果分析

可以看到只有四个点测试点通过,而其他的测试点全部超时。这时注意到N的取值范围达到了1010,所以很明显暴力求解无法满足时间要求。

方案二(组合数与二分查找:100分)

解题思路与代码

杨辉三角和组合数相关,可以表示为C(a,b)的形式,0<=b<=a。同时组合数的计算公式为:

C(a,b) = a!/(b!*(a-b)!)
思路:因为“从上到下,从左到右”,因此从三角形中间划一条垂线,则N一定位于左边。然后,我们发现从右上到左下的每一条斜行(将全是1的情况暂时忽略)都存在这样的规律:
  1. 开头的数为C(2x,x),x从1开始递增,例如2是C(2,1),6是C(4,2)......

  2. 每一斜行的递增规律是C(2x++,x),例如6是C(4,2),10是C(5,2)......

  3. 我们可以发现例如数字6有两个,而我们想输出的是位置最靠上的,则我们只需从下面斜排开始往上找N就可以保证N的位置一定是最小的。因为N最大不超过10e9,而C(32,16)已经大于10e9了,因此从x为16的斜排开始循环找N(采用二分法去找)

实现的代码如下:


global n
n = int(input())
# 计算阶乘

def C(b,a):
    '''计算组合数C(b,a)'''
    sum = 1
    i = b
    j =1
    while(j<=a):
        sum = sum*i/j
        i -= 1
        j += 1
        # 如果比目标数大就直接返回
        if sum>n:
            return sum
    return sum

def judge(x):
    # 每一个斜行的开头都是C(2x,x),从右上到左下,2x逐渐加一
    MIN = 2*x
    # 这里令右边界为n,因为C(n,x)一定大于n
    MAX = n
    while(MAX>MIN):
        mid = MIN+MAX>>1
        if C(mid,x)>=n:
            '''说明n在{MIN,mid}中'''
            MAX = mid
        else:
            MIN = mid + 1
    
    if (C(MAX,x)==n):
        # print(MAX)
        # print(x)
        print(int((1+MAX)*MAX/2)+x+1)
        return True
    else:
        return False
            
if n==1:
    print(1)
else:
    x = 16
    while(x>=0):
        if judge(x):
            break
        x -= 1

评测结果

结果分析与反思

主要是利用了二分查找的思路,同时也要注意查照时组合数不必全部计算出来,当大于我们要找的数时就可以直接返回。

同时,在python中,计算最终结果时,我一开始写的是int((1+MAX)*MAX/2+x+1),但是会出现结果太大的时候最后几位为0的情况,如下图所示:

这里暂时没有找到合理的解释,估计是何python的底层设计有关,改成int((1+MAX)*MAX/2)+x+1即可。

总结

这题好像是某一届的倒数第二题,属于较难的一道,大部分人可能都会直接使用暴力模拟来解题,这样虽然不能得到满分但是可以拿到一部分的分(同时速度快)。
在做题时需要关注题目给出的时间要求、空间要求、取值范围等,设计出最合适的算法。
总的来说,仍需要多加练习,在比赛时也要学会取舍(毕竟在这么短的时间内能全部满分做出来的需要运气与实力相兼并)。

posted @ 2022-03-10 20:42  律四  阅读(255)  评论(0编辑  收藏  举报