网易2017春招笔试真题编程题集合
网易2017春招笔试真题编程题集合
题目来源:牛客网 https://www.nowcoder.com/profile/7952866/test/7811777/83061
1、双核处理
题目描述
一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务。n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间。
输入描述
输入包括两行: 第一行为整数n(1 ≤ n ≤ 50)
第二行为n个整数lengthi,表示每个任务的长度为length[i]kb,每个数均为1024的倍数。
输出描述 :输出一个整数,表示最少需要处理的时间
输入例子 :5
3072 3072 7168 3072 1024
输出例子: 9216
思路分析:
题意很清晰,就是给一个数组,要我们把他分成两份并分别求和,使得这两个和的最大值最小。我下意识的想法是枚举出所有有可能的和,但是复杂度大概是O(2^n) ,貌似会超时。可是仔细一看,length[i] 的取值在[1, 4096] 之间,那么最多n个数的和的范围肯定在[n, 4096n] 之间。
代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<set> 4 using namespace std; 5 int n; 6 int a[51]; 7 set<int>s; 8 int sum = 0; 9 int main() 10 { 11 cin >> n; 12 for (int i = 0; i<n; i++) 13 { 14 int tmp; 15 cin >> tmp; 16 a[i] = tmp / 1024; 17 sum += a[i]; 18 } 19 s.insert(0); 20 for (int i = 0; i<n; i++) 21 { 22 set<int>added; 23 for (set<int>::iterator it = s.begin(); it != s.end(); it++) 24 { 25 added.insert(*it + a[i]); 26 } 27 s.insert(added.begin(), added.end()); 28 } 29 int ans = sum; 30 for (set<int>::iterator it = s.begin(); it != s.end(); it++) 31 { 32 ans = min(ans, max(*it, sum - *it)); 33 } 34 cout << ans * 1024 << endl; 35 }
结果:
2、赶去公司
题目描述
终于到周末啦!小易走在市区的街道上准备找朋友聚会,突然服务器发来警报,小易需要立即回公司修复这个紧急bug。假设市区是一个无限大的区域,每条街道假设坐标是(X,Y),小易当前在(0,0)街道,办公室在(gx,gy)街道上。小易周围有多个出租车打车点,小易赶去办公室有两种选择,一种就是走路去公司,另外一种就是走到一个出租车打车点,然后从打车点的位置坐出租车去公司。每次移动到相邻的街道(横向或者纵向)走路将会花费walkTime时间,打车将花费taxiTime时间。小易需要尽快赶到公司去,现在小易想知道他最快需要花费多少时间去公司。 输入描述: 输入数据包括五行:
第一行为周围出租车打车点的个数n(1 ≤ n ≤ 50)
第二行为每个出租车打车点的横坐标tX[i] (-10000 ≤ tX[i] ≤ 10000)
第三行为每个出租车打车点的纵坐标tY[i] (-10000 ≤ tY[i] ≤ 10000)
第四行为办公室坐标gx,gy(-10000 ≤ gx,gy ≤ 10000),以空格分隔
第五行为走路时间walkTime(1 ≤ walkTime ≤ 1000)和taxiTime(1 ≤ taxiTime ≤ 1000),以空格分隔
输出描述: 输出一个整数表示,小易最快能赶到办公室的时间
输入例子: 2
-2 -2
0 -2
-4 -2
15 3
输出例子: 42
思路分析
基础题,先算步行的时间,再枚举每个打车点算出打的时间,找到时间最短的即可。直接进行比较就可以,没有复杂的过程。
代码:
1 #include<iostream> 2 #include<vector> 3 using namespace std; 4 int main() 5 { 6 int n; 7 cin >> n; 8 vector<int> taxiX(n, 0); 9 vector<int> taxiY(n, 0); 10 for (int i = 0; i < n; i++) 11 cin >> taxiX[i]; 12 for (int i = 0; i < n; i++) 13 cin >> taxiY[i]; 14 int gx, gy; 15 cin >> gx >> gy; 16 int taxiTime, walkTime; 17 cin >> walkTime >> taxiTime; 18 int ans = walkTime*(abs(gx) + abs(gy)); //不打车所用的时间 19 for (int j = 0; j < n; j++) 20 { 21 int tmp = walkTime*(abs(taxiX[j]) + abs(taxiY[j])) + taxiTime*(abs(gx - taxiX[j]) + abs(gy - taxiY[j])); 22 if (tmp < ans) 23 ans = tmp; 24 } 25 cout << ans << endl; 26 return 0; 27 }
结果:
3、调整队形
题目描述
在幼儿园有n个小朋友排列为一个队伍,从左到右一个挨着一个编号为(0~n-1)。其中有一些是男生,有一些是女生,男生用’B’表示,女生用’G’表示。小朋友们都很顽皮,当一个男生挨着的是女生的时候就会发生矛盾。作为幼儿园的老师,你需要让男生挨着女生或者女生挨着男生的情况最少。你只能在原队形上进行调整,每次调整只能让相邻的两个小朋友交换位置,现在需要尽快完成队伍调整,你需要计算出最少需要调整多少次可以让上述情况最少。例如: GGBBG -> GGBGB -> GGGBB 这样就使之前的两处男女相邻变为一处相邻,需要调整队形2次 输入描述: 输入数据包括一个长度为n且只包含G和B的字符串.n不超过50.
输出描述: 输出一个整数,表示最少需要的调整队伍的次数
输入例子: GGBBG
输出例子: 2
思路分析:
我们对于串中第一个’B’然后计算把它swap到第一个位置需要多少次,第二个’B’swap到第二个位置需要多少次…依次类推..
然后对于’G’同理, 最后取个较小值即为答案。
代码:
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 7 int main() 8 { 9 string str; 10 cin >> str; 11 int boyCount = 0, girlCount = 0, boy = 0, girl = 0; 12 for (int i = 0; i < str.size(); i++) 13 { 14 if (str[i] == 'B') 15 { 16 boyCount += i - boy; 17 boy++; 18 } 19 else 20 { 21 girlCount += i - girl; 22 girl++; 23 } 24 } 25 cout << min(boyCount, girlCount) << endl; 26 }
结果:
4、魔力手环
题目描述
小易拥有一个拥有魔力的手环上面有n个数字(构成一个环),当这个魔力手环每次使用魔力的时候就会发生一种奇特的变化:每个数字会变成自己跟后面一个数字的和(最后一个数字的后面一个数字是第一个),一旦某个位置的数字大于等于100就马上对100取模(比如某个位置变为103,就会自动变为3).现在给出这个魔力手环的构成,请你计算出使用k次魔力之后魔力手环的状态。
输入描述: 输入数据包括两行: 第一行为两个整数n(2 ≤ n ≤ 50)和k(1 ≤ k ≤ 2000000000),以空格分隔 第二行为魔力手环初始的n个数,以空格分隔。范围都在0至99.
输出描述: 输出魔力手环使用k次之后的状态,以空格分隔,行末无空格。
输入例子: 3 2
1 2 3
输出例子: 8 9 7
思路分析:
直接按逻辑进行运算,比较费时,推荐使用快速矩阵幂算法,这里采用的是直接算。
代码:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 int main() 7 { 8 int n, k; 9 cin >> n >> k; 10 vector<long> arr ; 11 for (int i = 0; i <= n; i++) 12 arr.push_back(0); 13 for (int i = 1; i <= n; i++) 14 cin >> arr[i]; 15 vector<long> tmp = arr; 16 for (int j = 1; j <= k; j++) 17 { 18 int i = 1; 19 while (i < n ) 20 { 21 tmp[i] += arr[i + 1]; 22 if (tmp[i]>100) 23 tmp[i]%= 100; 24 i++; 25 } 26 while (i==n) 27 { 28 tmp[i] += arr[1]; 29 if (tmp[i]>100) 30 tmp[i] %= 100; 31 i++; 32 } 33 arr = tmp; 34 } 35 cout << arr[1]; 36 for (int i = 2; i <= n; i++) 37 cout <<" "<< arr[i]; 38 cout << endl; 39 return 0; 40 }
结果:
5、集合
题目描述
小易最近在数学课上学习到了集合的概念,集合有三个特征:1.确定性 2.互异性 3.无序性. 小易的老师给了小易这样一个集合: S = { p/q | w ≤ p ≤ x, y ≤ q ≤ z } 需要根据给定的w,x,y,z,求出集合中一共有多少个元素。小易才学习了集合还解决不了这个复杂的问题,需要你来帮助他。
输入描述: 输入包括一行: 一共4个整数分别是w(1 ≤ w ≤ x),x(1 ≤ x ≤ 100),y(1 ≤ y ≤ z),z(1 ≤ z ≤ 100).以空格分隔
输出描述: 输出集合中元素的个数
输入例子: 1 10 1 1
输出例子: 10
思路分析
题意就是给分数判重,显然我们不能直接算,因为浮点数是不精确的,乘以1.0000就可以了,然后丢进set里就好了。
代码:
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 int getSetNum(int w, int x, int y, int z) 5 { 6 int count = 0; 7 set<double> s; 8 for (int i = w; i <= x; i++) 9 for (int j = y; j <= z; j++) 10 { 11 s.insert(i*1.0000 / j); 12 } 13 count = s.size(); 14 return count; 15 } 16 int main() 17 { 18 int w, x, y, z; 19 cin >> w >> x >> y >> z; 20 int ans; 21 ans = getSetNum(w, x, y, z); 22 cout << ans << endl; 23 return 0; 24 }
结果:
6、奇怪的表达式求值
题目描述
常规的表达式求值,我们都会根据计算的优先级来计算。比如/的优先级就高于+-。但是小易所生活的世界的表达式规则很简单,从左往右依次计算即可,而且小易所在的世界没有除法,意味着表达式中没有/,只有(+, - 和 )。现在给出一个表达式,需要你帮忙计算出小易所在的世界这个表达式的值为多少
输入描述: 输入为一行字符串,即一个表达式。其中运算符只有-,+,*。参与计算的数字只有0~9. 保证表达式都是合法的,排列规则如样例所示。
输出描述: 输出一个数,即表达式的值
输入例子: 3+5*7
输出例子: 56
思路分析:
关键之处在于:输入的一个数字和下一个数字之间肯定隔着一个操作符,所以在第一个for循环的时候i=i+2,依次取数,再取操作符进行运算。
代码:
#include<iostream> #include<string> using namespace std; int main() { string str; cin >> str; int ans = str[0] - '0'; for (int i = 1; i < str.length() - 1; i += 2) { //关键之处i+=2 if (str[i] == '*') ans = ans * (str[i + 1] - '0'); else if (str[i] == '+') ans = ans + (str[i + 1] - '0'); else { ans = ans - (str[i + 1] - '0'); } } cout << ans << endl; return 0; }
结果:
7、小易记单词
题目描述
小易参与了一个记单词的小游戏。游戏开始系统提供了m个不同的单词,小易记忆一段时间之后需要在纸上写出他记住的单词。小易一共写出了n个他能记住的单词,如果小易写出的单词是在系统提供的,将获得这个单词长度的平方的分数。注意小易写出的单词可能重复,但是对于每个正确的单词只能计分一次。
输入描述: 输入数据包括三行:
第一行为两个整数n(1 ≤ n ≤ 50)和m(1 ≤ m ≤ 50)。以空格分隔
第二行为n个字符串,表示小易能记住的单词,以空格分隔,每个单词的长度小于等于50。
第三行为m个字符串,系统提供的单词,以空格分隔,每个单词的长度小于等于50。
输出描述: 输出一个整数表示小易能获得的分数
输入例子: 3 4
apple orange strawberry strawberry orange grapefruit watermelon
输出例子: 136
思路分析
把能记住的单词丢进set里,可以去除重复单词,合理利用set的insert函数,然后判断每一个是不是在系统提供的集合里即可。
代码:
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<set> 5 //为了避免重复,将单词放入set里 6 using namespace std; 7 8 int main() 9 { 10 int n, m; 11 cin >> n >> m; 12 set<string> str1, str2; 13 for (int i = 0; i<n; i++) 14 { 15 //读入小易记住的单词 16 string str; 17 cin >> str; 18 str1.insert(str); 19 } 20 for (int i = 0; i<m; i++) 21 { 22 //读入系统提供的单词 23 string str; 24 cin >> str; 25 str2.insert(str); 26 } 27 int ans = 0; 28 for (set<string>::iterator it = str1.begin(); it != str1.end(); it++) 29 { 30 if (str2.find(*it) != str2.end()) 31 { 32 //find()函数返回指向查找元素的迭代器,如果不存在返回set的end()迭代器. 33 ans += it->length() * it->length();//计算分数:单词长度的平方 34 } 35 } 36 cout << ans << endl; 37 }
结果:
8、消除重复元素
题目描述
小易有一个长度为n序列,小易想移除掉里面的重复元素,但是小易想是对于每种元素保留最后出现的那个。小易遇到了困难,希望你来帮助他。
输入描述:
输入包括两行: 第一行为序列长度n(1 ≤ n ≤ 50)
第二行为n个数sequencei,以空格分隔
输出描述: 输出消除重复元素之后的序列,以空格分隔,行末无空格
输入例子: 9
100 100 100 99 99 99 100 100 100
输出例子: 99 100
思路分析
从后向前先判重后加入即可,合理利用集合set的insert函数,去除重复元素
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<set> 5 6 //从后向前先判重后加入即可。 7 using namespace std; 8 int main() 9 { 10 int n; 11 cin >> n; 12 int a[51] = { 0 }; 13 vector<int> arr; 14 set<int> s; 15 for (int i = 0; i < n; i++) 16 cin >> a[i]; 17 for (int i = n - 1; i >= 0; i--) 18 { 19 if (s.find(a[i]) == s.end()) 20 { 21 s.insert(a[i]); 22 arr.push_back(a[i]); 23 } 24 } 25 cout << arr[arr.size() - 1]; 26 for (int i = arr.size() - 2; i >= 0; i--) 27 { 28 cout << " " << arr[i]; 29 } 30 cout << endl; 31 return 0; 32 }
结果:
9、涂棋盘
题目描述
小易有一块n*n的棋盘,棋盘的每一个格子都为黑色或者白色,小易现在要用他喜欢的红色去涂画棋盘。小易会找出棋盘中某一列中拥有相同颜色的最大的区域去涂画,帮助小易算算他会涂画多少个棋格。
输入描述: 输入数据包括n+1行:
第一行为一个整数n(1 ≤ n ≤ 50),即棋盘的大小
接下来的n行每行一个字符串表示第i行棋盘的颜色,’W’表示白色,’B’表示黑色
输出描述: 输出小易会涂画的区域大小
输入例子: 3
BWW
BBB
BWB
输出例子: 3
思路分析:
注意,只是找某一列的最大区域,并不是整个棋盘的最大区域,所以比较简单。
代码:
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 using namespace std; 5 6 int main() 7 { 8 string str[52]; 9 int n; 10 cin >> n; 11 for (int i = 0; i < n; i++) 12 cin >> str[i]; 13 int maxCnt = 0;//保存最大区域的值 14 for (int j = 0; j < n; j++) 15 { 16 int cnt = 1;//临时保存每一列的最大区域的值 17 for (int i = 1; i < n; i++) 18 { 19 if (str[i][j] == str[i - 1][j]) 20 { 21 cnt++; 22 } 23 else 24 { 25 maxCnt = max(maxCnt, cnt); 26 cnt = 1; 27 } 28 29 } 30 maxCnt = max(maxCnt, cnt); 31 } 32 cout << maxCnt << endl; 33 return 0; 34 }
结果: