腾讯2021校园招聘-后台&综合-第二次笔试 Apare_xzc

腾讯2021校园招聘-后台&综合-第二次笔试 Apare_xzc

2020.9.6 20:00-22:00


5道编程题,500分


第一题:链表的公共部分

题意:

        给定两个长度分别为n,m的链表,1<=n,m<=1000,000, 输出两个链表的公共部分

分析:双指针即可

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
int a[N],b[N]; 
int main(void) {
	int n,m;
	scanf("%d",&n);
	for(int i=0;i<n;++i)
		scanf("%d",a+i);
	scanf("%d",&m);
	for(int i=0;i<m;++i) 
		scanf("%d",b+i);
	int i = 0, j = 0;
	while(i<n&&j<m) {
		if(a[i]==b[j]) printf("%d ",a[i]),++i,++j;
		else if(a[i]<b[j]) ++j;
		else ++i;
	}
	printf("\n");
	return 0;
}

100%


第二题:求消息最多有几个人知道

题意:

        有n个人,有m个小组,每个小组有ki个人。一个人可以属于多个小组,也可以不属于任何一个小组。一个消息,初始0号知道,然后同一小组的人相互告知,求最后多少人知道?包括0。n<=1E5

分析:并查集即可。但是人的编号不一定是0~n-1

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int pre[N];
void init() {
	for(int i=0;i<N;++i) pre[i] = i;
}
int Find(int x) {
	return x==pre[x]?x:pre[x] = Find(pre[x]);
} 
void join(int x,int y) {
	int fx = Find(x), fy = Find(y);
	if(fx!=fy) pre[fy] = fx;
}
int main(void) {
	int n,m,x,y;
	scanf("%d%d",&n,&m);
	init();
	set<int> st;
	for(int i=1;i<=m;++i) {
		scanf("%d",&x);
		vector<int> v;
		for(int j=0;j<x;++j)
			scanf("%d",&y),v.push_back(y),st.insert(y);
		for(int i=1;i<x;++i) join(v[i],v[i-1]);
	} 
	int par = Find(0);
	int ans = 0;
	for(auto it:st) {
		if(Find(it)==par) ++ans;
	}
	printf("%d\n",ans);
	return 0;
}

100%


第三题:

题意:

        给定n个字符串和一个K, 每个字符串记录出现的次数,输出前K个字符串和后K个字符串。输出2*K行, 前K行,按第一关键字为出现次数从大到小,第二关键字为字典序从小到大。后K行,按第一关键字为出现次数从小到大,第二关键字为字典序从小到大输出。

分析:自定义排序即可。

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
map<string,int> mp;
struct Node{
	string str;
	int cnt;
	bool operator < (const Node& rhs)const{
		return cnt==rhs.cnt?str<rhs.str:cnt>rhs.cnt;
	}
	Node(string _str,int _cnt) {
		str = _str; cnt = _cnt;
	}
};
bool cmp(const Node& a,const Node& b) {
	return a.cnt==b.cnt?a.str<b.str:a.cnt<b.cnt;
}
int main(void) {
	int n,k;
	ios::sync_with_stdio(false); 
	scanf("%d%d",&n,&k);
	string s;
	for(int i=1;i<=n;++i) {
		cin>>s;
		++mp[s];
	} 
	vector<Node> v;
	for(auto it:mp) {
		v.push_back(Node(it.first,it.second));
	}
	sort(v.begin(),v.end());
	for(int i=0;i<k;++i) {
		cout<<v[i].str<<" "<<v[i].cnt<<"\n";
	}
	sort(v.begin(),v.end(),cmp);
	for(int i=0;i<k;++i) {
		cout<<v[i].str<<" "<<v[i].cnt<<"\n";
	}
	return 0;
}

100%


第四题

题意:

        给一个序列,长度为n,n<=200,000。求删除每个数之后,序列的中位数。保证n为偶数。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
pair<int,int> a[N]; 
int ans[N];
int main(void) {
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;++i) {
		a[i].second = i;
		scanf("%d",&a[i].first);
	}
	sort(a,a+n);
	int tot = n-1;
	int mid = tot/2;
	for(int i=0;i<n;++i) { //删除第i个数
		if(i<=mid) ans[a[i].second] = a[mid+1].first;
		else ans[a[i].second] = a[mid].first; 
	}
	for(int i=0;i<n;++i)
		printf("%d\n",ans[i]);
	return 0;
}

100%


第五题:

题意:

        有一个长度为2*n的格子,上面放了n个红棋子和n个黑棋子
n = 3
BRRBRB
先输入n,然后输入长度为2n的字符串
然后下面是2
n个数,第i个数,代表第i个位置的棋子在颜色相同的棋子中的序号

你每次操作可以 交换两个相邻的棋子。
现在要使得相同颜色的棋子,从左到右序号递增
问最少要多少次交换?

3
BRRBRB
2 3 1 1 2 3

分析:只过了5%,看样例是用选择排序的思想,先搞定一个颜色,再搞定另一个颜色,用选择排序的思想,每次先把当前最大的移动到合适的位置。但是移动R会对B的位置产生影响,猜想要先R后B,先B后R,每个从后往前排,从前往后排,然后4个结果取最小的。不知道这样贪心的正确性。只过了5%

#include <bits/stdc++.h>
using namespace std;
const int N = 3000+100;
/*
题目表述:有一个长度为2*n的格子,上面放了n个红棋子和n个黑棋子
n = 3
BRRBRB
先输入n,然后输入长度为2*n的字符串 
然后下面是2*n个数,第i个数,代表第i个位置的棋子在颜色相同的棋子中的序号

你每次操作可以 交换两个相邻的棋子。
现在要使得相同颜色的棋子,从左到右序号递增
问最少要多少次交换?
 

*/
int a[N*2];
char s[N*2];
struct Node{
	int val; //值的大小    or  类型 'R' 'B' 
	int pos; //原始位置        第几小  
	Node(int v=0,int p=0){
		val = v; pos = p;
	} 
	bool operator < (Node& rhs)const{
		return val < rhs.val;
	}
};
int p[N*2]; 
Node r[N*2]; //记录棋盘的现状 
int posR[N]; //记录R的第x小的位置 
int posB[N]; //记录B的第x小的位置 
int len;
void show() {
	static int cont = 0;
	printf("第%d次交换:\n",cont++);
	for(int j=1;j<=len;++j)
		cout<<(char)r[j].val;cout<<endl;
	for(int j=1;j<=len;++j) cout<<r[j].pos<<" ";cout<<endl<<endl;
}
int main(void) {
	int n;
//	freopen("in.txt","r",stdin);
	scanf("%d",&n);
	scanf("%s",s+1);
	len = 2*n;
	for(int i=1;i<=len;++i) 
		scanf("%d",p+i);
	for(int i=1;i<=len;++i) {
		if(s[i]=='R') {
			r[i].val = 'R'; //记录类型 
			r[i].pos = p[i]; //记录第几小
			posR[p[i]] = i; //记录B的第p[i]小在位置i
		} 
		else { //s[i]=='B' 
			r[i].val = 'B'; //记录类型
			r[i].pos = p[i];//记录第几小
			posB[p[i]] = i; //记录B的第p[i]小在位置i 
		} 
	}
	
	int ans = 0;
	for(int i=n;i>1;--i) { //先处理R 
		int rightest_pos = -1;
		for(int j=0;j<i;++j) {
			if(posR[j]>posR[i]) {
				rightest_pos = max(rightest_pos,posR[j]);
			}
		}
		if(rightest_pos==-1) continue;
		ans += rightest_pos-posR[i]; 
		Node Ri_tmp = r[posR[i]]; //记录的是R的第i大的类型和第几大 
		for(int j=posR[i];j<rightest_pos;++j) {
		r[rightest_pos] = Ri_tmp;
		posR[Ri_tmp.pos] = rightest_pos; 
	} 
	
	//再处理B
	for(int i=n;i>1 ;--i) {  
		int rightest_pos = -1;
		for(int j=0;j<i;++j) {
			if(posB[j]>posB[i]) {
				rightest_pos = max(rightest_pos,posB[j]);
			}
		}
		if(rightest_pos==-1) continue;
		ans += rightest_pos-posB[i]; 
		Node Ri_tmp = r[posB[i]]; 
		for(int j=posB[i];j<rightest_pos;++j) {
			r[j] = r[j+1];
			if(r[j].val=='R') posR[r[j].pos] = j; //更新位置 
			else posB[r[j].pos] = j;
		}
		r[rightest_pos] = Ri_tmp;
		posB[Ri_tmp.pos] = rightest_pos; 
	}  
	cout<<ans<<endl;
	
	return 0;
}

2020.9.7
6:56


猜你喜欢

转载自blog.csdn.net/qq_40531479/article/details/108440073