字节跳动2019春招研发部分编程题汇总

ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443

第一题

[编程题]万万没想到之聪明的编辑
时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

我叫王大锤,是一家出版社的编辑。我负责校对投稿来的英文稿件,这份工作非常烦人,因为每天都要去修正无数的拼写错误。但是,优秀的人总能在平凡的工作中发现真理。我发现一个发现拼写错误的捷径:

1. 三个同样的字母连在一起,一定是拼写错误,去掉一个的就好啦:比如 helllo -> hello
2. 两对一样的字母(AABB型)连在一起,一定是拼写错误,去掉第二对的一个字母就好啦:比如 helloo -> hello
3. 上面的规则优先“从左到右”匹配,即如果是AABBCC,虽然AABB和BBCC都是错误拼写,应该优先考虑修复AABB,结果为AABCC

我特喵是个天才!我在蓝翔学过挖掘机和程序设计,按照这个原理写了一个自动校对器,工作效率从此起飞。用不了多久,我就会出任CEO,当上董事长,迎娶白富美,走上人生巅峰,想想都有点小激动呢!
……
万万没想到,我被开除了,临走时老板对我说: “做人做事要兢兢业业、勤勤恳恳、本本分分,人要是行,干一行行一行。一行行行行行;要是不行,干一行不行一行,一行不行行行不行。” 我现在整个人红红火火恍恍惚惚的……

请听题:请实现大锤的自动校对程序

输入描述:
第一行包括一个数字N,表示本次用例包括多少个待校验的字符串。

后面跟随N行,每行为一个待校验的字符串。

输出描述:
N行,每行包括一个被修复后的字符串。

输入例子1:
2
helloo
wooooooow

输出例子1:
hello
woow

模拟,使用一个临时数据来存储答案,在这个数组上增加删除
Code

#include<bits/stdc++.h> 
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;

int n;
char s[100005],t[100005];
int main(){
	scanf("%d",&n);
	fo(i,1,n){
		scanf("%s",s+1);
		int len = strlen(s+1);
		int o=0;
		for(int i=1; i<=len; i++){
			t[++o]=s[i]; // 增加一个
			// 是否删除(在新队列的原数据进行比较-----!!!) 
			if(o-2>0 && t[o]==t[o-1] && t[o]==t[o-2]){
				o--;
			}
			if(o-3>0 && t[o]==t[o-1] && t[o-2]==t[o-3]){
				o--;
			}
		}
		for(int i=1; i<=o; i++){
			printf("%c",t[i]);
		}
		putchar(10);
	} 
	return 0;
}

第二题

[编程题]万万没想到之抓捕孔连顺
时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 128M,其他语言256M

我叫王大锤,是一名特工。我刚刚接到任务:在字节跳动大街进行埋伏,抓捕恐怖分子孔连顺。和我一起行动的还有另外两名特工,我提议

1. 我们在字节跳动大街的N个建筑中选定3个埋伏地点。
2. 为了相互照应,我们决定相距最远的两名特工间的距离不超过D。

我特喵是个天才! 经过精密的计算,我们从X种可行的埋伏方案中选择了一种。这个方案万无一失,颤抖吧,孔连顺!
……
万万没想到,计划还是失败了,孔连顺化妆成小龙女,混在cosplay的队伍中逃出了字节跳动大街。只怪他的伪装太成功了,就是杨过本人来了也发现不了的!

请听题:给定N(可选作为埋伏点的建筑物数)、D(相距最远的两名特工间的距离的最大值)以及可选建筑的坐标,计算在这次行动中,大锤的小队有多少种埋伏选择。
注意:
1. 两个特工不能埋伏在同一地点
2. 三个特工是等价的:即同样的位置组合(A, B, C) 只算一种埋伏方法,不能因“特工之间互换位置”而重复使用


输入描述:
第一行包含空格分隔的两个数字 N和D(1 ≤ N ≤ 1000000; 1 ≤ D ≤ 1000000)

第二行包含N个建筑物的的位置,每个位置用一个整数(取值区间为[0, 1000000])表示,从小到大排列(将字节跳动大街看做一条数轴)

输出描述:
一个数字,表示不同埋伏方案的数量。结果可能溢出,请对 99997867 取模

输入例子1:
4 3
1 2 3 4

输出例子1:
4

例子说明1:
可选方案 (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)

输入例子2:
5 19
1 10 20 30 50

输出例子2:
1

例子说明2:
可选方案 (1, 10, 20)

组合数学,使用一个滑动窗口来定位一段符合要求的区间,然后选择第一个后S的方案数为C(2,x),累加即可

#include<bits/stdc++.h> 
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int mod = 99997867;
int n,d;
int a[1000005];
ll ans;
int main(){
	cin>>n>>d;
	fo(i,1,n)cin>>a[i];
	sort(a+1,a+1+n);
	int j=0;
	for(int i=1; i<=n; i++){
		while(j<n && a[j+1]-a[i]<=d)j++;
		if(j-i>=2){
			ans = (ans + 1ll*(j-i)*1ll*(j-i-1)/2)%mod;
		}		
	}
	cout<<ans<<endl;
	return 0;
}

第三题

[编程题]雀魂启动!
时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

小包最近迷上了一款叫做雀魂的麻将游戏,但是这个游戏规则太复杂,小包玩了几个月了还是输多赢少。
于是生气的小包根据游戏简化了一下规则发明了一种新的麻将,只留下一种花色,并且去除了一些特殊和牌方式(例如七对子等),具体的规则如下:

总共有36张牌,每张牌是1~9。每个数字4张牌。
你手里有其中的14张牌,如果这14张牌满足如下条件,即算作和牌
14张牌中有2张相同数字的牌,称为雀头。
除去上述2张牌,剩下12张牌可以组成4个顺子或刻子。顺子的意思是递增的连续3个数字牌(例如234,567等),刻子的意思是相同数字的3个数字牌(例如111,777)

例如:
1 1 1 2 2 2 6 6 6 7 7 7 9 9 可以组成1,2,6,7的4个刻子和9的雀头,可以和牌
1 1 1 1 2 2 3 3 5 6 7 7 8 9 用1做雀头,组123,123,567,789的四个顺子,可以和牌
1 1 1 2 2 2 3 3 3 5 6 7 7 9 无论用1 2 3 7哪个做雀头,都无法组成和牌的条件。

现在,小包从36张牌中抽取了13张牌,他想知道在剩下的23张牌中,再取一张牌,取到哪几种数字牌可以和牌。

输入描述:
输入只有一行,包含13个数字,用空格分隔,每个数字在1~9之间,数据保证同种数字最多出现4次。

输出描述:
输出同样是一行,包含1个或以上的数字。代表他再取到哪些牌可以和牌。若满足条件的有多种牌,请按从小到大的顺序输出。若没有满足条件的牌,请输出一个数字0

输入例子1:
1 1 1 2 2 2 5 5 5 6 6 6 9

输出例子1:
9

例子说明1:
可以组成1,2,6,7的4个刻子和9的雀头

输入例子2:
1 1 1 1 2 2 3 3 5 6 7 8 9

输出例子2:
4 7

例子说明2:
用1做雀头,组123,123,567或456,789的四个顺子

输入例子3:
1 1 1 2 2 2 3 3 3 5 7 7 9

输出例子3:
0

例子说明3:
来任何牌都无法和牌

判断能不能和牌…注意单张牌数不能超过5.可以回溯判断…

#include<bits/stdc++.h> 
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;


int a[15],t[15];
bool ok;
void dfs(int now){
	if(ok)return;
	if(now==12){
		for(int i=1; i<=9; i++){
			if(a[i]==2){
				ok = true;
				return;
			}
		}
	}
	for(int i=1; i<=9; i++){
		if(a[i]>=3){
			a[i]-=3;
			dfs(now+3); 
			a[i]+=3;
		}
		if(i+2<=9 && a[i]>=1 && a[i+1]>=1 && a[i+2]>=1){
			a[i]--;a[i+1]--;a[i+2]--;
			dfs(now+3);
			a[i]++;a[i+1]++;a[i+2]++;
		}
	}
}
int main(){
	fo(i,1,13){
		int x;cin>>x;
		t[x]++;	
	}
	bool find = 0;
	for(int i=1; i<=9; i++){
		ok = false;
		fo(j,1,9)a[j]=t[j];
		if(a[i]>=4)continue;
		a[i]++;
		dfs(0);
		if(ok){
			printf("%d ",i);
			find = 1;
		}
	} 
	if(!find){
		cout<<0;
	}
	return 0;
}

第四题

[编程题]特征提取
时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

       小明是一名算法工程师,同时也是一名铲屎官。某天,他突发奇想,想从猫咪的视频里挖掘一些猫咪的运动信息。为了提取运动信息,他需要从视频的每一帧提取“猫咪特征”。一个猫咪特征是一个两维的vector<x, y>。如果x_1=x_2 and y_1=y_2,那么这俩是同一个特征。
       因此,如果喵咪特征连续一致,可以认为喵咪在运动。也就是说,如果特征<a, b>在持续帧里出现,那么它将构成特征运动。比如,特征<a, b>在第2/3/4/7/8帧出现,那么该特征将形成两个特征运动2-3-47-8。
现在,给定每一帧的特征,特征的数量可能不一样。小明期望能找到最长的特征运动。

输入描述:
第一行包含一个正整数N,代表测试用例的个数。

每个测试用例的第一行包含一个正整数M,代表视频的帧数。

接下来的M行,每行代表一帧。其中,第一个数字是该帧的特征个数,接下来的数字是在特征的取值;比如样例输入第三行里,2代表该帧有两个猫咪特征,<11><22>
所有用例的输入特征总数和<100000

N满足1≤N≤100000,M满足1≤M≤10000,一帧的特征个数满足 ≤ 10000。
特征取值均为非负整数。

输出描述:
对每一个测试用例,输出特征运动的长度作为一行

输入例子1:
1
8
2 1 1 2 2
2 1 1 1 4
2 1 1 2 2
2 2 2 1 4
0
0
1 1 1
1 1 1

输出例子1:
3

例子说明1:
特征<1,1>在连续的帧中连续出现3次,相比其他特征连续出现的次数大,所以输出3

因为是要求是连续的。所以每个状态严格依赖于上一个状态。所以使用两个map,滚动一下。

#include<bits/stdc++.h> 
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;

int T,n;
map<pair<int,int>, int > now,last;
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		int ans = 0;
		fo(i,1,n){
			now.clear();
			int x;cin>>x;
			fo(k,1,x){
				int a,b;
				cin>>a>>b; 
				now[{a,b}] = last[{a,b}]+1;
				ans = max(ans, now[{a,b}]);
			}
			last = now;
		}
		cout<<ans<<endl;
	}
	return 0;
}

第五题

[编程题]毕业旅行问题
时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

小明目前在做一份毕业旅行的规划。打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次。由于经费有限,希望能够通过合理的路线安排尽可能的省一些路上的花销。给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销。

输入描述:
城市个数n(1<n≤20,包括北京)

城市间的车票价钱 n行n列的矩阵 m[n][n]

输出描述:
最小车费花销 s

输入例子1:
4
0 2 6 5
2 0 4 4
6 4 0 2
5 4 2 0

输出例子1:
13

例子说明1:
共 4 个城市,城市 1 和城市 1 的车费为0,城市 1 和城市 2 之间的车费为 2,城市 1 和城市 3 之间的车费为 6,城市 1 和城市 4 之间的车费为 5,依次类推。假设任意两个城市之间均有单程票可购买,且票价在1000元以内,无需考虑极端情况。

状压DP裸题…好久没过了…生疏

#include<bits/stdc++.h> 
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;

int n;
int a[25][25];
void solve(){
	int dp[20][1<<20];
	memset(dp,0x3f, sizeof(dp));
	dp[0][(1<<n)-1] = 0; // 当前0,1未访问 
	for(int s=(1<<n)-1; s>=0; s--){
		for(int v=0; v<n; v++){
			// next u
			for(int u=0; u<n; u++){
				if((s>>u)&1){ // 未访问
					dp[u][s&~(1<<u)] = min(dp[u][s&~(1<<u)], dp[v][s]+a[v][u]);
				}
			}
		}
	} 
	cout<<dp[0][0];
}
int main(){
	cin>>n;
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			cin>>a[i][j];
		}
	}
	solve();
	return 0;
} 

第六题

[编程题]找零
时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

Z国的货币系统包含面值1元、4元、16元、64元共计4种硬币,以及面值1024元的纸币。现在小Y使用1024元的纸币购买了一件价值为的商品,请问最少他会收到多少硬币?

输入描述:
一行,包含一个数N。

输出描述:
一行,包含一个数,表示最少收到的硬币数。

输入例子1:
200

输出例子1:
17

例子说明1:
花200,需要找零824块,找12个64元硬币,3个16元硬币,2个4元硬币即可。

???暴力…

#include<bits/stdc++.h> 
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;

int n;
int ans;
int calc(int res, int t){
	while(res>=t){
		int m = res/t;
		res -= m*t;
		ans+=m;
	}
	return res;
}
int main(){
	cin>>n;
	int t = 1024-n;
	t = calc(t,1024);
	t = calc(t,64);
	t = calc(t,16);
	t = calc(t,4);
	t = calc(t,1);
	cout<<ans;
	return 0;
} 

第七题

[编程题]机器人跳跃问题
时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

机器人正在玩一个古老的基于DOS的游戏。游戏中有N+1座建筑——从0到N编号,从左到右排列。编号为0的建筑高度为0个单位,编号为i的建筑的高度为H(i)个单位。 

起初, 机器人在编号为0的建筑处。每一步,它跳到下一个(右边)建筑。假设机器人在第k个建筑,且它现在的能量值是E, 下一步它将跳到第个k+1建筑。它将会得到或者失去正比于与H(k+1)与E之差的能量。如果 H(k+1) > E 那么机器人就失去 H(k+1) - E 的能量值,否则它将得到 E - H(k+1) 的能量值。

游戏目标是到达第个N建筑,在这个过程中,能量值不能为负数个单位。现在的问题是机器人以多少能量值开始游戏,才可以保证成功完成游戏?

输入描述:
第一行输入,表示一共有 N 组数据.

第二个是 N 个空格分隔的整数,H1, H2, H3, ..., Hn 代表建筑物的高度

输出描述:
输出一个单独的数表示完成游戏所需的最少单位的初始能量

输入例子1:
5
3 4 3 2 4

输出例子1:
4

输入例子2:
3
4 4 4

输出例子2:
4

输入例子3:
3
1 6 4

输出例子3:
3

简单二分…别人的数学解法太强了…

#include<bits/stdc++.h> 
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
ll n,h[100005],mx;
bool ok(ll x){
	for(int i=1; i<=n; i++){
		ll t = x;
		if(h[i]>x){
			x-=(h[i]-x);
		}else{
			x+=(x-h[i]);
		}
		if(x>mx)return true;
		if(x<0){
			return false;
		}
	}
	return true;
}
void solve(){
	fo(i,1,n){
		mx = max(mx, h[i]);
	}
	ll l=0, r=mx, ans=mx;
	while(l<=r){
		ll mid = (l+r)>>1;
		if(ok(mid)){
			ans = mid;
			r = mid - 1;
		}else{
			l = mid + 1;
		}
	}
	cout<<ans;
} 
int main(){
	cin>>n;
	fo(i,1,n)cin>>h[i];
	solve();
	return 0;
}

别人的

input()
arr = list(map(int, input().split(' ')))
# 假设跳跃前能力为E,要跳的高度为H,那么跳跃后的能量就是2E-H,
# 那么跳跃后的能量加上高度就是跳跃前的两倍,然后从后往前逆推。
E = 0    # 跳到最后一步的能力值设为0
arr.reverse()
for H in arr:
    E = (E + H + 1) >> 1
print(E)
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页