提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本次的笔试还是比较简单的,我大概用了45分钟左右完成了ak
不过还没有收到面试通知(写完的时候已经收到了嘿嘿嘿)。
所以准备写题解(蒟蒻)来攒一波人品
`提示:本文的代码不是笔试时的通过代码,所以可能有些BUG
一、模糊字符串?
作者:pikeduo
链接:https://nowcoder.net/discuss/868691?type=2&channel=-1&source_id=discuss_tag_discuss_hot_nctrack
来源:牛客网
我们约定"模糊回文字母串"的定义如下: 对于一一个含有英文字母的字符申。
如果满足如下规则: 1)读的时候字母不区分大小写; 2)非字母字符均当作同一字符读叹: 若从左往右读和从右往左读是一样的, 那么就称之为模糊回文字母串。
例如,“a#&A”. “a+b-a”. “abA”. "ab(%BA’均属于模朝回文字母串。 现给定一一个含有字母的字符串s,请编写函数判断字符丰s经过有限次 的字符位置调整后能否变成一个模糊回文字母串,若可以则返true,不 可以则返回false. 输入用例 a#&A 输出 true 输入用例 -A+(AAa)bB 输出 true
题目详情连接
本题非常简单,只需要记录一下每个字符的数量,如果出现两个奇数以上那么就返回false就ok了
#include<bits/stdc++.h> //牛客是可以用万能头的
using namespace std;
typedef long long ll;
int t,i,j;
int a[30];
int main(){
string s;
cin>>s;
int b = 0;//记录非字母字符的个数
int len = s.length();
for(int i=0;i<len;i++){
if(s[i]>='a' && s[i] <='z')
a[s[i] - 'a' + 1]++;
else if(s[i]>='A' && s[i] <='Z')
a[s[i] - 'A' + 1]++;
else
b++;
}
int f = 2;
if(b % 2) f--;
for(int i=0;i<30;i++){
if(a[i] % 2)f--;
}
if(f < 1)cout<<"false";
else cout<<"true";
return 0;
}
二、小明买补给
作者:pikeduo
链接:https://nowcoder.net/discuss/868691?type=2&channel=-1&source_id=discuss_tag_discuss_hot_nctrack
来源:牛客网
小明想从A徒步到B,总跆程需要M天,路程中为了确保安全,小明每天需 要消耗1份食物。 在起点及路程当中,零星分布着N个朴給站,可以补充食物,不同朴给站 的食物价格可能不同。 请问小明若要安全完成徒步,最少需要花费多少钱呢?
输入描述:
第一行为两个正整教M、N,代表总路程M天,补给站个数N
接下来N行,每行有两个非负整数A. B代表-一个补输站, 表示第A天经 过该补给站,每份食物的价格为B元, A是从0开始严格递增的,即起点一定有补给站,补给站是按位置顺序 给出的,且同一个位置最多有一个补给站。
输出描述: 输出一个整数,表示最少花费的金额
输入
5 4
0 2
1 3
2 1
3 2
输出
7
说明 在第0天买2份食物花费4元,在第2天买3份食物花费3元,共花费7元
题解:显然的贪心题,由于每个加油站的补给数量是无限的,而且可以携带的补给也没有限制(如果有的话,这题将会变得很难),所以我们贪心的考虑只在当前最低价的地方来补充补给,最后一次补充补给时直接购买到终点的量。
#include<bits/stdc++.h> //牛客是可以用万能头的
using namespace std;
typedef long long ll;
int t,i,j;
int a[100010],b[100010];//数据范围根据题目来开
int m,n,ta,tb;
int main(){
cin>>m>>n;
for(int i=0;i<n;i++){
cin>>a[i]>>b[i];
}
int ans = 0;//答案
int pos = 0;//代表当前位置
int price = b[0];//代表当前价格
while(a[pos] < m){
int j = pos+1;
if(j>10)break;
//while 循环用来找到 后面第一个价格低于当前价格的补给站位置
while(j < n && b[j] > price) j++;
if(j < n){
ans += price * (a[j] - a[pos]); //在pos处购买补给
pos = j;//来到下一个位置
price = b[j];//更新价格
}else break;
}
//别忘了从最后一个点到 终点还是需要买补给的
ans += price * (m - pos);
cout<<ans;
return 0;
}
三、分地区
作者:pikeduo
链接:https://nowcoder.net/discuss/868691?type=2&channel=-1&source_id=discuss_tag_discuss_hot_nctrack
来源:牛客网
经过500年的大战,X星球的人们在魔法天神的带领下终于消灭了外来物种 Y,然而,长时间的战争使得X军球秋序遭到破坏,人员管理混乱,为了尽 快恢复秩序,建设美好生活乐园,土地如何划分、人员如何管理成为当前 必须要解决的问题。 x星球由多个魔法部落组成,每个魔法部落由多个魔法师组成,每个魔法 师有一个单线联系的来自同一部落的师父。
为了公平,X星球上的魔法师之问达成共识,按照每个部满的魔法师人数 比例多少划分土地。 现在,星球上由于长时间大战,魔法师分散星球各地,请你协助魔法天神 按照各部落魔法使人数划分土地。
注意:
1.x星球土地面积共有579万平方干米
2.魔法天神需要把星球的土地全部划分到各个部落中
3.一个部落中的师徒关系有可能出现环,即A是B的师傅,B是C的师 傅, C又是的A师傅
输入描述: .
第一行星球总人数n 和师徒关系数m
(从1、n代表星球上的所有人, 1<n<=200 )
(0<=m<=200)
其他m行 ,一共m组师徒关系数据 :徒弟 师傅
输出描述:
第一行 星球总部落数
第二行由多到少每个部落 分得的土地面积(单位为万平力平米,保 留整敫(向下取整>即可)
输入
8 6
1 3
5 3
7 5
6 2
4 8
4 6
输出
2
289 289
说明 8个人,有6个师徒关系,根据师徒关系可以得出 1, 3, 5,7属于一个部落 2,4, 6, 8属于一个部落 所以这个星球共有2个部落, 由于两个部落人数一致,所以平分579万平方千米的土地,即分别 分得209万平方千米
题解:这题目很容易看出来是要求连通块的数量,但是碍于数据范围比较大(具体忘记了,但是最后的20分应该是很大的),所以不能直接暴力求,所以我们需要用到并查集这一数据结构,没用过并查集的可以先百度一下,并查集通常还会运用在求最小生成树等等题目上。
如果能够想到并查集,那么这题也就很容易了
#include<bits/stdc++.h> //牛客是可以用万能头的
using namespace std;
typedef long long ll;
int t,i,j;
int f[100010];//数据范围根据题目来开
int peo[100010];//记录每个种族的人数
int m,n,ta,tb;
const int M = 579;//总面积
int find(int x){
//求父节点的同时进行路径压缩
return f[x] == x?x:(f[x] = find(f[x]));
}
void init(int x){
//初始化,每个人的父节点都是自己本身
for(int i=0;i<=x;i++)f[i] = i;
}
bool cmp(int a,int b){
return a>b;
}
int main(){
cin>>n>>m;
init(n);//初始化
for(int i=0;i<m;i++){
cin>>ta>>tb;
int fa = find(ta);
int fb = find(tb);
if(fa != fb)//两个人之前不属于同一个部落
{
f[fa] = fb;
}
}
//统计部落数
int ans = 0;
for(int i=1;i<=n;i++){
int f = find(i);
if(f == i){
ans++;
}
peo[f]++; //f部落的人数
}
cout<<ans<<"\n";
sort(peo+1,peo+1+n,cmp);
for(int i=1;i<=n;i++){
if(peo[i] != 0){
cout<<peo[i] * M / n<<" ";
}else break;
}
return 0;
}
四、反转字符串
小红拿列了一个长度为n的、仅由大小写字母组成的字符串, 小红有q次操作,每次操作可以选择一个区间, 将该区间的字母大小写翻 转。 请你输出最终的字符串。 输入描述: 第一行输入两个正整数n和q,用空格隔开。代表字符事长度和操 作次数。 第二行输入一个长度为n的、仅由大小写字母组成的字符申。 接下来的q行,每行输入两个正整数l和r,代表小红操作的区 间。 输出描述: 输出最终的字符串。
输入
5 3
aCbqE
1 3
2 5
5 5
输出
ACbQE
说明
第一次操作[1,3]区间,字符串变成AcBqE
第二次操作[2,5] 区间,字符申变成ACbQe
第三次操作[5,5]区间,字符串变成ACbQE
题解:这题如果对于每一次的区间操作都进行暴力修改的话复杂度会来到n*q,显然是过不了的(根据网友的情况来看应该是会得到50分);
那么对于这一题来说,我的解法是用 一个数组来记录 每个位置的修改情况。也就是差分+前缀和
我们可以显然的得到:如果一个位置被修改次数是偶数的话,那么就相当于不需要修改。只有被修改次数为奇数的话才需要修改。
具体代码如下:
#include<bits/stdc++.h> //牛客是可以用万能头的
using namespace std;
typedef long long ll;
int t,i,j;
int n,q,l,r;
int a[100010];
string s;
char change(char c){
if( c <= 'Z' && c>= 'A') return c-'A'+'a';
else return c-'a'+'A';
}
int main(){
cin>>n>>q;
cin>>s;
for(int i=0;i<q;i++){
cin>>l>>r;
//差分数组的修改:从l -> r 这一段的修改次数都+1
a[l]++;
a[r+1]--;
}
for(int i=1;i<=n;i++){
a[i] += a[i-1];//前缀和
if(a[i] % 2)//奇数需要修改
{
printf("%c",change(s[i-1]));//注意下标问题
}else{
printf("%c",s[i-1]);
}
}
return 0;
}
总结
这次的笔试难度感觉不是很难,但是比较考验同学的算法知识广度(比如说要会写并查集、差分等等)。如果能想到的话,那么都很容易写出来的(模板题吧感觉像)。
这次的题解就写到这了。
祝各位一帆风顺,顺遂安康。