2020字节跳动笔试题

第一题

小明总是睡过头,所以他定了很多闹钟,只有在闹钟响的时候他才会醒过来并且决定起不起床,从他起来算起他需要X分钟到达教室,上课时间为当天的A时B分,请问他最晚可以什么时候起床。
输入描述:第一行为一个正整数,表示闹钟的数量N(N<=100)
接下来的N行每行两个整数,表示这个闹钟响起的时间为Hi时Mi分
接下来的一行包含一个整数,表示从起床起他需要X(0<=X<=100)分钟到达教室
接下来的一行包含两个整数,表示上课时间为A时B分
数据保证至少有一个闹钟可以让牛牛及时到达教室
输出描述:输出两个整数表示牛牛最晚起床时间
示例一:
输入
3
5 0
6 0
7 0
59
6 59
输出
6

分析

比较简单,我是把 (小时*60+分钟+到达教室需时X) 作为时间来进行比较,与上课时间差值最小的就是答案。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;

int n,x;
int a[110],b[110];
int h,m;
int main()
{
    cin>>n;
    for (int i=1 ; i<=n ; i++){
        cin>>a[i]>>b[i];
    }
    cin>>x;
    cin>>h>>m;
    int mintime=INF,ans;
    for (int i=1 ; i<=n ; i++){
        int now = 60*h+m - (60*a[i]+b[i]+x);
        if (now >= 0 && now < mintime){
            mintime = now;
            ans = i;
        }
    }
    cout<<a[ans]<<" "<<b[ans]<<endl;
    return 0;
}

第二题

小明和安琪是好朋友,最近,他们的谈话被一家侦探机构监控,所以他们想将他们的谈话内容进行加密处理,于是,他们发明了一种新的加密方式。每条信息都被编译成二进制数B(明文),长度为N,然后该信息被写下K次,每次向右移动0,1,……,K-1位。
例如: B = 1001010 K = 4
1001010
  1001010
    1001010
      1001010
对每一列进行异或操作,并且把最终结果记录下来,成为密文S,例如上述例子的结果为1110100110
最后,将编码的信息S和K发送给安琪
安琪需要一份代码来实现解密过程,你能帮助她吗?
输入描述:第一行输入两个整数N和K
第二行输入一个二进制字符串S,长度为N+K-1
输出描述:输出明文B
示例1:
输入
7 4
1110100110
输出
1001010
示例2:
输入
6 2
1110001
输出
101111

分析

简单模拟一下就好,显然第一个位置的数就是结果的第一位,而第二个位置的数异或结果的第一位等于结果的第二位,这个原理是由于异或操作可逆,观察规律,在这个例子中,结果第三位是由给出数的前三位异或得,结果第四位是由给出数的前四位异或得,结果第五位是由给出数的第二至第五位异或得,所以我用了一个now来存当前数字,如果 i 还不到 k 那只需要把当前数与now异或即可,当 i 比 k 大时,now既与当前数异或又与 结果的第 i - k 位异或,这样做就能保证now是由k个数异或而来。
越讲越乱了,有点绕,最好自己推写一遍找规律。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<stack>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;

int n,k;
string ss;
int ans[1000];
int main()
{
    cin>>n>>k;
    cin>>ss;
    ans[0] = ss[0]-'0';
    int now = ans[0];
    for (int i=1 ; i<n ; i++){
        ans[i] = now ^ (ss[i]-'0');
        now ^= ans[i];
        if (i >= k-1) now ^=  ans[i-k+1];
    }
    for (int i=0 ; i<n ; i++)
        cout<<ans[i];
    cout<<endl;
    return 0;
}

第三题

我叫王大锤,是一家互联网公司的老板。快到年底了,要给员工发奖金,真头疼,大环境这么差,怎么才能尽可能的少发点,同时还能让大家怨气少一点呢?公司的位子是连成一排的,每个人最多打听到和自己相邻左右两个座位的同事的奖金,我决定这样发:
每个人至少发100块;
论资排辈,每个人加入公司的年限是公开的,如果一个员工A加入公司的时间比邻座的同事B早,那么A至少比B多拿100块,这样才能让老员工心理平衡。
我特喵真是个天才!将人性理解的如此透彻,做一个小公司的老板真是屈才了。
给出大锤公司员工的座位表,以及每个员工的入职时间,计算大锤最少要发多少奖金。
输入描述:第一行只有一个整数N(1<=N<=1000),表示员工人数。
第二行有N个正整数,代表每个员工的入职年限,排列顺序为员工的座位顺序。
输出描述:一个数字,代表大锤最少需要发的奖金数。
示例1:
输入
4
3 9 2 7
输出
600

示例2:
输入
3
1 1 1
输出
300

示例3:
输入
5
1 2 3 4 5
输出
1500

分析(这个分析有问题)

贪心,开始的时候最小奖金为100元,那么第一个人就先给最小奖金100元,i 从2 遍历到n,假如第i个人的工龄比第i-1个人的长,那么第i个人的奖金是第i-1个人的奖金加100,假如相同工龄,那就相同奖金,假如第i个人工龄更短,那么只需要发给他最小奖金即可,但需要注意的是,假如第i-1个人已经发了最小奖金,那么第i个人工龄更短就可以发比最小奖金还少100的奖金,这种情况下需要更新一次最小奖金,然后继续遍历。
此时,由于最小奖金可能是一个负数,我们需要把所有人的奖金都加上 (100-最小奖金),这样奖金最少的人拿到的是100。
例如 工龄为 5 4 3 6
第一个人给100,最小奖金为100,第二个人给0,最小奖金为0,第三个人给-100,最小奖金为-100,第四个人给0,此时最小奖金为-100,那么每个人都加上(100-(-100))=200, 即 300 200 100 200。

代码

#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;

int n,ans;
int years[1100],reward[1100];

int main()
{
    cin>>n;
    for (int i=1 ; i<=n ; i++)
        cin>>years[i];
    reward[1] = 100;
    int minn = 100;
    ans = 100;
    for (int i=2 ; i<=n ; i++){
        if (years[i] > years[i-1])
            reward[i] = reward[i-1] + 100;
        else if (years[i] == years[i-1])
             reward[i] = reward[i-1];
        else if (years[i] < years[i-1]){
            reward[i] = min(minn,reward[i-1]-100);
            minn = min(minn,reward[i]);
        }

        ans += reward[i];
    }
    cout<<ans+(100-minn)*n<<endl;
    return 0;
}

距离这篇博客发布已经过去半年,我在做一道力扣的相似的题时突然发现这种做法是有问题的,比如1 4 3 2 1,我的算法会跑出100 200 100 0 -100 的结果,然后为了将最小值补成100最后成了 300 400 300 200 100,显然不是最优结果,这道题的确是贪心,但是不能用我这个思路,正确做法可以使用两个reward数组,第一个从左往右遍历,第一个人给100, 如果第i个人比第i-1个人工龄长则reward1[i] = reward1[i-1]+100,否则令reward1[i]=100,然后从右往左遍历,第n个人给100,如果第i个人比第i+1个人工龄长则reward2[i] = reward2[i+1]+100否则给100,最后遍历一些sum += max(reward1[i], reward2[i]),这样就能保证拿到的奖金满足相邻大小关系。
具体做法见leetcode题库135分发糖果。
如果这个错误思路干扰到您我表示万分抱歉!我没有思考仔细!

第四题

小明练习跑步,他家附近的街道是棵树,这棵树上的点按1到n编号,任意两点间互相可达,并且有且只有一条路,每条路的距离都是1,需要在树上找一条路来跑,小明对3很感兴趣,所以他想知道所有跑道距离和%3=0,1,2的道路总长度一共各有多长,即树上任意两点间距离%3=K的距离和。
输入描述:第一行一个n,点数n<=1e5
接下来n-1行每行u,v表示一条无向边
输出描述:一行三个整数,分别代表%3=0,1,2的两点距离的距离和,结果取模1e9+7
示例1:
输入
3
1 2
2 3
输出
0 2 2

这个树论就不会了,感觉挺难的。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值