2021届秋招——腾讯数据分析笔试

1.字符串匹配

现在给你一个只包含"()[]"括号的字符串,问你至少加多少个字符是合法的,对于字符串合法的定义为:
1.字符串为空是合法的
2.若字符串A合法,则字符串(A), [A]也是合法的
3.若字符串A和字符串B均合法,则AB合法
详情参考: 动态规划

输入: 第一行输入一个字符串s,保证只有题目要求的字符 1 <= len(s) <= 200
输出: 输出最少需要添加几个字符可以构成合法的字符串

思想:
这是一个区间动态规划问题:
状态定义:使用二维dp,dp[i][j]表示从s[i]到s[j]的最少添加括号个数
初始化:单独一个字符时,dp[i][j]=1,因为一个字符必定需要添加一个括号,其他值先赋值为0
状态转移方程:
循环遍历区间长度(区间长度m从1到n),每次考虑[i,j]内的区间(i从0开始,j=i+m),
如果s[i]和s[j]匹配,那么dp[i][j]=dp[i+1][j-1],也即括号里面部分需要添加的最少括号数.
如果s[i]和s[j]不能匹配,那么必定存在一个分界位第k位,使得从第i位到第k位所需要加的最少括号数量dp[i][k]和第k+1位到第j位所需要加的括号数量dp[k+1][j]相加起来的和能够凑成整个问题的最优值,即dp[i][j]=min(dp[i][j], dp[i][k] + dp[k+1][j])

def match(a, b):
    # 判断是否匹配
    if a == '[' and b == ']':
        return True
    if a == '(' and b == ')':
        return True
    return False
def kuohaomatch(s):
    n = len(s)
    dp = [[n] * n for _ in range(n)]#nxn大小的矩阵,因为求最小,初始n
    #初始化,自己到自己最少添加1
    for i in range(n):
        dp[i][i] = 1
    #依次遍历区间长度维1,2,3,...,n
    for m in range(1, n + 1):
        for i in range(n - m):
            j = i + m
            if match(s[i], s[j]):#能匹配的话
                dp[i][j] = dp[i + 1][j - 1]
            else:#不能匹配的话
                for k in range(i, j):
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j])
    return dp[0][n - 1]#返回从s[0]到s[n]的最少添加括号个数
s = '((]]()]'
print(kuohaomatch(s)) #结果:5

2.求面积

一个二次曲线 y = A x 2 + x + B , x = C , x = D y=Ax^2+x+B, x=C, x=D y=Ax2+x+B,x=C,x=D,与 x x x轴围城的面积。

思想:
当A=0时,围城的区域是梯形
当A1!=0时,围城的区域是曲面,利用积分的思想:以直代曲,无线分割,求和近似
因为考虑到精度问题,C-D区间分割100万份,再分成1000,取每份中间的矩形*500,但是还是没通过所有用例。
考试的时候竟然numpy不能用!!!!

"""
   li=abs(d-c)/1000000
   sum1=0
   for i in range(0,1000000,1000):
       a1=c+(i+500)*li
       a2=c+(i+501)*li
       sum2=500*abs(a2-a1)*(a2+a*a2*a2+a*a1*a1+a1+2*b)
       sum1=sum1+sum2
   return sum1
 """
import numpy as np
n=int(input())
def fun(a,b,c,d):
    if c==d:
        return 0
    if not a:
        return(0.5*abs(d-c)*(c+d+2*b))
    if a!=0 and c!=d:
        li=np.linspace(c,d,1000000)
        sum1=0
        for i in range(0,len(li),1000):
            a1=li[i+500]
            a2=li[i+501]
            sum2=500*abs(a2-a1)*(a2+a*a2*a2+a*a1*a1+a1+2*b)
            sum1=sum1+sum2
        return sum1
ans=[]
for i in range(n):
    a,b,c,d=map(int,input().strip().split())
    s=fun(a,b,c,d)
    ans.append(s)
for i in range(len(ans)):
    print(ans[i],' ',)
    if i ==len(ans):
        print(ans[i])  

在这里插入图片描述

3.排列组合题

从N个人当中选出M个人组队,在M个人当中选出一个人当队长,当选出的集合相同时而当队长的人不一样时,则为两个不同的方案,请用代码实现共有多少中组队方案?

思想:
C(n,m)*m

n,m=list(map(int,input().split()))
print(Cfun(n,m)*m)

在这里插入图片描述

组合C(n,m)函数的实现

def Cfun(n,m):
    a=b=result=1
    if n<m:
        print("n不能小于m 且均为整数")  
    for j in range(0,m):
    #使用变量a,b 让所用的分母相乘后除以所有的分子
        a=a*(n-j)
        b=b*(m-j)
        result=a//b #在此使用“/”和“//”均可,因为a除以b为整数
    return result

排列A(n,m)函数的实现

def Afun(n,m):
    a=1
    if n<m:
        print("n不能小于m 且均为整数")  
    for j in range(0,m):
    #使用变量a,b 让所用的分母相乘后除以所有的分子
        a=a*(n-j)
    return a

小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌最多只能在歌单中出现一次,在不考虑歌单内歌曲的先后顺序的情况下,请问有多少种组成歌单的方法。

#接收输入
k = int(input())
a, x, b, y = list(map(int,input().split()))
#遍历
res = 0
# a*x+b*j=k有很多种情况,需要循环,确定从x中挑选出i首和y中选出j首,因为组合前后均不考虑顺序
for i in range(1,x+1):
    for j in range(1,y+1):
        if (i * a + j * b) == k:
            res = res + Cfun(x,i)*Cfun(y,j)#调用上面的组合函数
#取模打印
if i <1000000007:
    print(res)
else:
    print(res%1000000007)

4.图

题目忘记了,打算做个专场

5.最短路径

题目忘记了,打算做个专场

6.画图

画家小Q又开始他的艺术创作。小Q拿出了一块有NxM像素格的画板, 画板初始状态是空白的,用’X’表示。
小Q有他独特的绘画技巧,每次小Q会选择一条斜线, 如果斜线的方向形如’/’,即斜率为1,小Q会选择这条斜线中的一段格子,都涂画为蓝色,用’B’表示;如果对角线的方向形如’’,即斜率为-1,小Q会选择这条斜线中的一段格子,都涂画为黄色,用’Y’表示。
如果一个格子既被蓝色涂画过又被黄色涂画过,那么这个格子就会变成绿色,用’G’表示。
小Q已经有想画出的作品的样子, 请你帮他计算一下他最少需要多少次操作完成这幅画。

每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数N和M(1 <= N, M <= 50), 表示画板的长宽。
接下来的N行包含N个长度为M的字符串, 其中包含字符'B','Y','G','X',分别表示蓝色,黄色,绿色,空白。整个表示小Q要完成的作品。
输出描述:
输出一个正整数, 表示小Q最少需要多少次操作完成绘画。
输入
4 4
YXXB
XYGX
XBYY
BXXY
输出
3

思想:
因为’Y’只会以斜率 -1 出现,'B’只会以斜率 1 出现,所以这道题就变得十分简单。直接逐行逐列遍历,对于第 i 行第 j 列的元素 T[i][j],分析一下它的几种可能性如下:
1、T[i][j] == ‘Y’,此时只需看看它的左上角元素是否也为 ‘Y’ or ‘G’ 即可,如果是,那么该元素可以被上面的元素以同一笔绘制而成,否则,需要新起一笔,cnt += 1;
2、T[i][j] == ‘B’,观察它的右上角元素是否也为 ‘B’ or ‘G’ 即可,如若不是,cnt += 1;
3、T[i][j] == ‘G’,把上面两步都过一遍即可。
最后的 cnt 记录的便是最少用的笔数。

N, M = map(int, input().strip().split())
T = []
for i in range(N):
    T.append(input().strip())
cnt = 0
for i in range(N):
    for j in range(M):
        if T[i][j] == 'X': continue
        if T[i][j] in ['Y', 'G']:
            if i - 1 >= 0 and j - 1 >= 0 and T[i-1][j-1] in ['Y', 'G']: cnt += 0
            else: cnt += 1
        if T[i][j] in ['B', 'G']:
            if i - 1 >= 0 and j + 1 < M and T[i-1][j+1] in ['B', 'G']: cnt += 0
            else: cnt += 1
print(cnt)

7.最大公因数

**备注:不是特别懂这个题,欢迎大家评论。**


def gcd_2(a,b):		#求两个数的最大公约数
    """
    先用小的一个数除大的一个数,得第一个余数;
    再用第一个余数除小的一个数,得第二个余数;
    又用第二个余数除第一个余数,得第三个余数;
    这样逐次用后一个数去除前一个余数,直到余数是0为止。
    那么,最后一个除数就是所求的最大公约数(如果最后的除数是1,那么原来的两个数是互质数)。
    """
    a,b = max(a,b),min(a,b)
    if a%b == 0:
        return b
    else:
        return gcd_2(b,a%b)

def gcd_many(s):		#求全部的
    g = s[0]
    for i in range(1,len(s)):
        #求数组的最大公约数转变为求两个数的最大公约数
        g=gcd_2(g,s[i])
    return g
if __name__ == '__main__':
    data= list(map(int,input().split()))
    #存放最大公因数数组,默认删除从0-n-1
    ans=[]
    for i in range(len(data)):
        ans.append(gcd_many(data[i:]))
    ans_sort=sorted(ans)
    print('为最大公因数:')
    print(ans_sort)
    #存放删除的位置,调换位置
    res=[]
    for i in range(len(ans_sort)):
        aa=ans.index(ans_sort[i])+1
        if i>0 and aa in res :
            res.append(res[-1]+1)
        else:
            res.append(aa)
    print('为使最大公因数字典序最大,原来数组删除的顺序:')
    print(res)

在这里插入图片描述

思路:
找出数组中每个重复元素的个数并减去1=执行的操作

data=[1, 1, 2, 3, 4, 5, 6 ,7, 8, 8, 8, 9, 9, 10, 11, 12, 12]
data_set=list(set(data))#去重后的数组
ret = []
for i in data_set:
    data.remove(i)#对原数组都移除一个元素,剩下的都是有重复的元素
print(len(data))#5
  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值