字节跳动 8.25 笔试 第一、二、三、四题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_18310041/article/details/100068439

第一题

题目:假设用户a,b,c,如果a和b之间关系大于等于3,则a和b是一类;如果ab一类,bc一类,则abc一类,输入关系矩阵,返回类数。

思路:关系矩阵沿着对角线对称,因而只需要遍历(i, n) ,保存值大于等于3的关系,返回 n - 满足一类的长度,注意可能导致结果小于1,需要处理。

n = int(input())
line = []
for i in range(n):
    line.append(list(map(int, input().split())))
ans = []
for i in range(n):
    for j in range(i,n):
        if line[i][j] >= 3:
            ans.append([i,j])
count = n - len(ans)
count = max(count,1)
print(count)

第二题

题目:圆形花园入口有n个,修路时每个入口只能一条路,所有路不能相交。

思路:f(4) = 2, f(6) = 5, 发现正好是卡特兰数,h(0)=1,h(1)=1,递推式h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)

本题的特殊性在于如果入口是奇数,则向下求整;入口小于1,则返回 0


def fun(n):
    if n < 1:
        return 0
    if n == 1:
        return 1
    
    h = [0] * n
    h[0], h[1] = 1, 1
    for i in range(2, n):
        h[i] = 0
        for j in range(0,i):
            h[i]+= h[j] * h[i-1-j]
    return h[n//2] % 1000000007
a = int(input())
print(fun(a))

第三题

题目:2048,一个4x4的矩阵,上1下2左3右4运动,相同元素会合并且只会触发一次合并,且优先合并移动方向顶部的位置。

思路:把二维问题转化为一维解决,比如上下运动,其实就是对每一列操作,左右运动则是对每一行操作。操作的部分都是一模一样的,就是从顶部位置开始合并相同元素。[2,2,2,2] 往右边移动,这时候会变成[0,4,0,4] 需要去掉0,然后在左边加上缺失的0。最后在返回值时,上下运动需要转置数组。

由于顶部优先没有提前考虑,导致新程序运行时已提交了~~~(>_<)~~~,完整代码如下:

def fun(d, a):
    ans = []
   
    # 每一列处理
    for i in range(4):
        if d == 1 or d == 2:
            # 取每一列
            f = [_[i] for _ in a]
        
        if d == 3 or d == 4:
            # 取每一行
            f = a[i]
        
        if [_ for _ in f if _!=0] == []:
            ans.append([0] * 4)
        else:
            # 优先从左边开始合并
            if d == 1 or d == 3:
                for i in range(len(f)-1):
                    if f[i] == f[i+1]:
                        f[i+1] = f[i] * 2
                        f[i] = 0
            # 优先从右边开始合并
            if d == 2 or d == 4:
                for i in range(len(f)-2, -1, -1):
                    if f[i] == f[i+1]:
                        f[i+1] = f[i] * 2
                        f[i] = 0
            # 去掉0
            f = [_ for _ in f if _!=0]
            # 后面 + 0
            if d == 1 or d == 3:
                f += [0] * (4-len(f))
            # 前面 + 0
            if d == 2 or d == 4:
                f = [0] * (4-len(f)) + f
            ans.append(f)
    if d == 1 or d == 2:
        # 行列转置
        return list(map(list,zip(*ans)))
    if d == 3 or d == 4:
        return ans
   
    
print(fun(3,[[0,2,2,2],[0,2,2,2],[0,2,2,2],[0,2,2,2]]))

第四题

题目:糖果n个,如果糖果之间的最大公约数大于1,则两者有连接;求输出一个数,最多能得到多少糖果

思路:原始糖果数组的第一个元素放入新数组,然后依次判断原始数组的元素与新数组元素的最大公约数,如果满足条件则放入新数组,并在原始数组里面删除这些元素。每循环一次,判断一次新数组的长度

def hcf(x, y):
    """该函数返回两个数的最大公约数"""
    num = 1
    # 获取最小值
    if x > y:
        smaller = y
    else:
        smaller = x

    for i in range(1, smaller + 1):
        if (x % i == 0) and (y % i == 0):
            num = i

    return num


def fun(a):
    res = 0
    # 直到 原始数组为空
    while a:
        # 原始数组的第一个元素放入新数组
        line = [a.pop(0)]
        k = 0
        while True:
            # 如果满足条件则放入新数组
            add_list = [i for i in a if hcf(i, line[k]) > 1]
            line.extend(add_list)
            # 在原始数组里面删除这些元素
            for i in add_list:
                a.remove(i)
            # 从新数组的下一位元素开始遍历
            k += 1
            if k == len(line) - 1:
                break
        res = max(res, len(line))
        # print(line)
    return res

print(fun([20, 50, 22, 74, 9, 63]))

猜你喜欢

转载自blog.csdn.net/qq_18310041/article/details/100068439