【2020算法练习一】笔试算法题 快手2020校园招聘秋招笔试--算法A试卷

24 篇文章 1 订阅
21 篇文章 3 订阅

1.求解一元一次方程的正整数解

解方程在线做题

输入描述:

输入一行表示该一元一次方程,其中未知数为X,方程包含加法、减法、乘法。
字符串长度少于20个字符,保证为合法方程。
所有整数绝对值不超过10000000。

输出描述:

如果X有唯一正整数解,输出该答案。如果解为非正整数、不存在或解不唯一,输出-1。
示例1

输入
2*X=6
输出
3

示例2

输入
X+2*X=3*X
输出
-1
说明解不唯一

参考代码:

eq = input()
eq1 = eq.replace("=","-(") + ")" # 将等式进行了变形,生成了一个结果为0的算式
c = eval(eq1, {'X': 1j})# 并将x = 1j代入算式,然后计算j的值即可得到X值
print(int(-c.real/c.imag))

eval是Python的一个内置函数,这个函数的作用是,返回传入字符串的表达式的结果。想象一下变量赋值时,将等号右边的表达式写成字符串的格式,将这个字符串作为eval的参数,eval的返回值就是这个表达式的结果。
eval(expression[, globals[, locals]])
参数

  • expression – 表达式。
  • globals – 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
  • locals – 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。

这其实是算是一种投机取巧的方法,因为其中不含复数,所以假设X是负数,进行求解,如果这个算式中可以有虚部,就不能用这个方法了
用虚数1j代替X,让eval把X作为数计算,注意一定写1j才能被当成数
计算得到aj+b,由于这个式子我们知道等于0
方程的解就是-b/a,也就是-实部/虚部

2.[编程题]健身

在线测试网址
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 128M,其他语言256M
因为公司有免费健身福利,快手程序员老铁们都很爱健身,而且他们健身时像工作一样充满效率。
他们把健身过程神奇的简化了出来:健身有N种锻炼方式可选,器材可看成在一条直线上。
每种锻炼方式距门口Xi米,因为有的器材上可以支持多种锻炼方式,因此有可能出现两种锻炼方式的距离是一样的,即Xa = Xb。
老铁们一进健身房门口就开启健身形态,每走1米,就能获得1点锻炼效果值,而每种锻炼方式也有Ei的效果值,锻炼的过程就是从门口走到某种锻炼方式锻炼,然后到下一个方式锻炼,最后返回门口的过程。需要注意的是,锻炼过程中老铁们不会为了获得效果而刻意走回头路

老铁们很想知道如果想选择某几种锻炼方式,怎样获得最大锻炼效果。
输入描述:
第一行N,表示锻炼方式的个数
第二行N个整数,表示每种锻炼方式距门口的距离
第三行N个整数,表示每种锻炼方式的效果值

输出描述:
N个整数,第k行表示选择k种锻炼方式时获得的最大锻炼效果
输入例子1:
5
1 2 3 4 5
1 1 1 1 1
输出例子1:
11
12
13
14
15
例子说明1:
对于样例第一行,老铁选择去第5种锻炼方式,考虑来回路程,一共获得5+1+5点锻炼效果值

思路:
第一,不走回头路;
其次,要求最大; 可以看作一种贪心算法,随着贪心的增加,distance的增幅效果逐渐减小,所以distance和exp的增量是一个重要的参数
所以应当 尽可能大的距离*2+效果,即算出全部的距离+效果的值,取最大 ,取前k-1个最大效果

算法:

对于选k个建身器材,先选k-1个value最大的器材,再从剩下的里面找出(2d+value)最大的器材A。如果器材A的d比前面选的k-1个器材要大,那么最后一个器材就选A;
否则,就选value第k大的器材。(因为只有一个器材会影响最终练习效果的关于距离的部分)
这样可以保持训练效率最大化。

思路解析:
ei是能量,dist是距离
要求解 m a x ( e 1 + e 2 + e 3 + … + e n ) + m a x ( d i s t ∗ 2 ) max(e_1+e_2+e_3+…+e_n)+max(dist*2) max(e1+e2+e3++en)+max(dist2)
而dist和 e i e_i ei有关,
即求解 m a x ( e 1 , e 2 , e 3 + e n − 1 ) + m a x ( e n ) + m a x ( d i s t ∗ 2 ) max(e_1,e_2,e_3+e_{n-1})+max(e_n)+max(dist*2) max(e1,e2,e3+en1)+max(en)+max(dist2)
此时可看出,前n-1个一定是val的最大值,而 m a x ( e n ) + m a x ( d i s t ∗ 2 ) max(e_n)+max(dist*2) max(en)+max(dist2)可以看到要么是

  • 1. e n + d i s t ∗ 2 e_n+dist*2 en+dist2的和的值最大
  • 否则val最大,dist是前面的某个n的值。

所以应该找出前k-1个最大的E,剩下的如果器材A的d比前面选的k-1个器材要大,那么最后一个器材就选A;否则,就选value第k大的器材。

试了两种语言,
python版本100%通过:

代码:
N=int(input())
distance = input().split()
exp = input().split()
  
max_to_choose=[]
for i in range(0,N):
    info={'dist':int(distance[i]),'exp':int(exp[i])}
    max_to_choose.append(info)
max_exp=sorted(max_to_choose,key=lambda info:info['exp'],reverse=True) # 按照健身效果排序,由于排序保证是稳定的。所以健身效果相同时,距离大的在后面
 
max_dist=0
kmax_save=0
kmax_exp=[]
save_index=0
for i in range(0,N):
    if(i>0):
        kmax_save=kmax_save+max_exp[i-1]['exp']
        kmax_exp.append(kmax_save)
        if(max_exp[i-1]['dist']>max_dist):
            max_dist=max_exp[i-1]['dist']
    else:
        kmax_exp.append(0)
    maxval=0
    value=0
    if(save_index<=i):
        for k in range(i,N):
            value=max_exp[k]['exp']+max_exp[k]['dist']*2
            if(value>maxval):
                maxval=value
                save_index=k
    # 从剩下的里找出2d+V最大的的器材A
    if(max_dist<max_exp[save_index]['dist']):
        kmax_exp[i]=kmax_exp[i]+2*max_exp[save_index]['dist']+max_exp[save_index]['exp']
    else:
        kmax_exp[i]=kmax_exp[i]+2*max_dist+max_exp[i]['exp']
    
for km in kmax_exp:
    print(km)

c语言80%通过,应该是排序做的不够优化:

链接:https://www.nowcoder.com/questionTerminal/7f080ec10f4e46c2bd13ea8b565273d0?toCommentId=5783941
来源:牛客网

#include <stdio.h>
#include <stdlib.h>
void quick_sort(int s,int k,int a[][2])
{
    if(s<k)
    {
        int i=s,j=k;
        int tmp=a[i][0];
        int tmp2=a[i][1];
        while(i<j)
        {
 
            while(i<j && a[j][0]<tmp)
            {
                j--;
            }
            if(i<j)
            {
                a[i][0]=a[j][0];
                a[i][1]=a[j][1];
                i++;
            }
 
            while(i<j && a[i][0]>=tmp)
            {
                i++;
            }
            if(i<j)
            {
                a[j][0]=a[i][0];
                a[j][1]=a[i][1];
                j--;
            }
        }
        a[i][0]=tmp;
        a[i][1]=tmp2;
        quick_sort(s,i-1,a);
        quick_sort(i+1,k,a);
    }
}
 
void print(int a[][2],int p,int e)
{
    int i=0;
    for(i=p; i<=e; i++)
    {
        printf("exp:%d dist:%d\n",a[i][0],a[i][1]);
    }
    printf("\n");
}
 
void print_re(int kmax_exp[])
{
    int i=0;
    while(kmax_exp[i])
    {
        printf("%d\n",kmax_exp[i]);
        i++;
    }
}
int info[100000][2]= {0};
int kmax_exp[100000]= {0};
int choosed=0;
 
int main()
{
    int i=0,n=0;
    scanf("%d",&n);
    for(i=0; i<n; i++)
    {
        scanf("%d",&info[i][1]);
    }
    for(i=0; i<n; i++)
    {
        scanf("%d",&info[i][0]);
    }
    quick_sort(0,n-1,info); //复杂度n2
    //print(info,0,n-1);
    int k=0;
    int max_dist=0;
    int kmax_save=0;
 
    int save_index=-1;
    for(i=0; i<n; i++)
    {
        //先选k-1个value最大的器材
        if(i>0) //由于前k-1个始终相同,直接保存结果
        {
            kmax_save=kmax_save+info[i-1][0];
            kmax_exp[i]=kmax_save;
            choosed=i-1; //标记前i-1个为已经选择
            if(info[i-1][1]>max_dist)
            {
                max_dist=info[i-1][1];//保存最大距离
            }
        }
        //for(k=0;k<n;k++){
        //    printf("%d ",choosed[k]);
        //}
        //printf("\n");
        //print_re(kmax_exp);
        int exp=info[i][0]; //保存第k大的经验值
        int maxval=0;
        int value=0;
        //只有当en+dist*2最大的值被作为前面的
        //选择了之后才需要重新选择。从第k个开始找。
        if(save_index<=i)
        {
            for(k=i; k<n; k++)
            {
                //从剩下n-i个里面的选择一个en+dist*2最大的
                value=info[k][0]+info[k][1]*2;
                if(value>maxval)
                {
                    maxval=value;
                    save_index=k;//保存选择的这个剩下最大的器材的索引
                }
            }
        }
        //printf("maxdist:%d maxval: %d save_index:%d \n",max_dist,maxval,save_index);
        if(max_dist<info[save_index][1])
        {
            kmax_exp[i]=kmax_exp[i]+2*info[save_index][1]+info[save_index][0];
        }
        else
        {
            kmax_exp[i]=kmax_exp[i]+2*max_dist+exp;
        }
    }
    print_re(kmax_exp);
    return 0;
}

一些测试的例子:

5
1 4 5 6 7
10 2 9 1 1
输出应该是:
19
29
34
36
37
输入:
10
1 2 3 3 4 4 5 5 6 6
1 9 1 1 10 1 1 1 1 1
输出:
18
27
32
33
34
35
36
37
38
39
输入:
10
1 2 3 3 4 5 6 7 8 9
1 9 1 1 10 1 2 2 2 2
输出:
20
30
39
41
43
45
46
47
48
49

3.无重复字符最长子串

在线做题网址
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

输入描述:
输入字符串(长度<=100000)

输出描述:
不含有重复字符的最长子串长度

输入例子1:
abcabcbb
输出例子1:
3

例子说明1:
因为无重复字符的最长子串是"abc",所以其长度为 3。

输入例子2:
bbbbb
输出例子2:
1

例子说明2:
因为无重复字符的最长子串是"b",所以其长度为 1。

思路:

如果遇到重复的段,就进行比较,如果比之前的长,就刷新最大长度,清空目前段,并从头开始保存,
最后输出最大长度。

代码:
string=input()
length=0
detect=[]
max_length=0

for i in range(0,len(string)):
    if string[i] in detect:
        length=len(detect)
        if length>max_length:
            max_length=length
        # print(detect)
        detect=[]
        detect.append(string[i])
    else:
        detect.append(string[i])
length=len(detect)
if length>max_length:
    max_length=length
# print(detect)
print(max_length)

4.[编程题]推荐结果打散

在线做题网址
某个推荐系统会推荐出一系列的视频和图片结果,视频用V表示,图片用P表示,现在需要对推荐系统返回的结果进行打散,使得【图片P】的结果每N个里面最多出现1个,并且保证图片最早出现的位置不变,图片之前的相对顺序不变;
例如:“V_0”, “V_1”, “V_2”, “P_3”, “P_4”, “P_5”, “V_6”, “P_7”, “V_8”, “V_9”
表示: 10个结果中,位置 [0 1 2 6 8 9] 是 视频V的结果;位置 [3 4 5 7] 是 图片P的结果;
如果 要求 图片P 每3个里最多出1个,那么打散后的结果为: “V_0”, “V_1”, “V_2”, “P_3”, “V_6”, “V_8”, “P_4”, “V_9” (P_5 和 P_7 满足不了打散要求 被删除)
如果 要求 图片P 每2个里最多出1个,那么打散后的结果为: “V_0”, “V_1”, “V_2”, “P_3”, “V_6”, “P_4”, “V_8”, “P_5”, “V_9”, “P_7”

输入描述:
第1行输入为一个整数N(1~10),表示每N个结果里最多出1个图片结果;
第2行输入为一个整数M(1~100),表示有M个待处理的推荐结果
第3行到第2+M行为具体的M个待处理结果,每行具体为:字符串 V_ 或 P_打头,后面接输入时0~M-1的顺序标号

输出描述:
第1行为K,表示打散处理后结果的长度
第2到K+1行为打散后的结果,具体为:字符串 V_ 或 P_打头,后面接输入时0~M-1的顺序标号

输入例子1:

3
10
V_0
V_1
V_2
P_3
P_4
P_5
V_6
P_7
V_8
V_9

输出例子1:

8
V_0
V_1
V_2
P_3
V_6
V_8
P_4
V_9 
思路:

注意文中的定义是打散,也就是说,没出现P之前的V不要动,不要改变,
出现P之后的那些不符合排列要求的才需要打散。
所以,遇到P之前不变,遇到P之后,在两个不符合要求的P之间插入V即可。
设置一个计数器,检查P之间的间隔。

代码:
N = int(input())
M = int(input())
P_list=[]
res = []
last_P = -N
for i in range(M):
    input_s = input()
    if input_s[0] == 'P':
        P_list.append(input_s)
        if len(res)-last_P >= N:
            p = P_list.pop(0)
            res.append(p)
            last_P = len(res) - 1
    else:
        res.append(input_s)
        if len(res)-last_P >= N and len(P_list)>=1:
            p = P_list.pop(0)
            res.append(p)
            last_P = len(res) - 1
print(len(res))
for val in res:
    print(val)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值