牛客上看到别人分享的题目8月19日华为笔试题_技术交流_牛客网
Q1
给你N行M列的人,他们是一个方阵。左上角是(0,0),右下角是(n-1, m-1),最外圈的人顺时针报数,当他们报的数个位是7并且十位是奇数,就选出来。外圈报完了内圈接着报,一直到所有人都报完,问最后选出来的是哪些。
要求是10<=n,m<=1000,如果输入不合法,那么就是返回空数组
自己写了一下,如果理解怎么顺时针遍历的话,这题就很好处理,注意边界的处理以及坐标的存储就行
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool isOk(int num){
return num%10 == 7 && (num/10)%2 == 1;//个位是7,十位为奇数
}
int main(){
int m, n;
cin >> m >> n;
if(m < 10 || m > 1000 || n < 10 || n > 1000){
cout << "[" << "]" << endl;
return 0;
}
vector<pair<int, int>> res;//保存符合要求的数字
int i = 1;//计数器
int top = 0, bottom = m-1, left = 0, right = n-1;
while(i < m*n){
for(int col = left; col <= right; ++col){
if(isOk(i)) res.push_back({top, col});
++i;
}
++top;
for(int row = top; row <= bottom; ++row){
if(isOk(i)) res.push_back({row, right});
++i;
}
--right;
for(int col = right; col >= left; --col){
if(isOk(i)) res.push_back({bottom, col});
++i;
}
--bottom;
for(int row = bottom; row >= top; --row){
if(isOk(i)) res.push_back({row, left});
++i;
}
++left;
}
cout << "[";
for(int i = 0; i < res.size(); ++i){
cout << "[" << res[i].first << "," << res[i].second << "]";
if(i != res.size()-1) cout << ",";
}
cout << "]" << endl;
return 0;
}
Q2
组合计算:
给你N个节点,然后输入他们所在的高度,问最后的二叉树可以有几种,结果可能很大,对10^9+7取模
0<N<=1000,每个节点的所在高度小于N,大于等于0
这个代码好像处理大数是有问题的:如果在循环内乘法就已经溢出的话,循环外的取模也会出错,好像是要用到:lucas(数论定理)_百度百科,反正我是不懂。。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n;
cin >> n;//输入节点个数
if(n <= 0 || n > 1000){//边界判断
cout << 0 << endl;
return 0;
}
vector<int> v(n, 0);//节点的高度
for(int i = 0; i < n; ++i) cin >> v[i];//输入每个节点对应高度
sort(v.begin(), v.end());
int maxHeight = v.back();
vector<int> count(maxHeight+1, 0);
//记录每个高度对应的节点数量
for(int i = 0; i < v.size(); ++i) ++count[v[i]];
int res = 1;
bool flag = 0;//标志位,如果出现每一层的节点数大于容纳量,则置位
int maxNumOfNode = 1;//记录每层的最多能容纳的节点数量(第一层最多为1)
for(int i = 0; i < count.size(); ++i){
if(count[i] > maxNumOfNode){//该高度对应的节点数超过二叉树容纳量
flag = 1;
cout << 0 << endl;//二叉树为0种
break;
}
if(count[i] < maxNumOfNode){
//这一层可以容纳maxNmOfNode个节点,而节点数有count[i]个,种类数相当于组合数
//从maxNumOfNode个位置中,选出count[i]个来
int beichu = 1;//被除数
int chu = 1;//除数
for (int j = 0; j < count[i]; ++j) {//计算组合
beichu *= maxNumOfNode - j;
chu *= j+1;
}
beichu /= chu;//组合数
res *= beichu;//乘以该层的组合数
}
//当count[i] == maxNumOfNode,说明该层满载,不会对二叉树种数做出贡献
maxNumOfNode = count[i] * 2;//下一层最多容纳节点数量等于该层节点数量 * 2
}
if(!flag){
res = res % (1000000000 + 7);
cout << res << endl;
}
return 0;
}
咨询大佬之后修改如下,可以实现把组合数计算出来方便查表,也方便取模运算:
#include <iostream>
#include <vector>
#include <algorithm>
#define MAXN 1002
using namespace std;
const long long MOD = 1e9+7;
long long c[MAXN][MAXN];//记录组合的个数
void init() {
c[0][0] = 1;
c[1][0] = 1;
c[1][1] = 1;
for (int i = 2;i <= 1000;++i) {
c[i][0] = 1;//第一列
for (int j = 1;j <= i;++j) c[i][j] = (c[i-1][j] + c[i-1][j-1])%MOD; //在 i个 中取出 j个
}
}
int main(){
int n;
cin >> n;//输入节点个数
if(n <= 0 || n > 1000){//边界判断
cout << 0 << endl;
return 0;
}
init();//初始化组合数组
vector<int> v(n, 0);//节点的高度
for(int i = 0; i < n; ++i) cin >> v[i];//输入每个节点对应高度
sort(v.begin(), v.end());
int maxHeight = v.back();//最大高度
vector<int> count(maxHeight+1, 0);
for(int i = 0; i < v.size(); ++i) ++count[v[i]]; //记录每个高度对应的节点数量
long long res = 1;
bool flag = 0;//标志位,如果出现每一层的节点数大于容纳量,则置位
int maxNumOfNode = 1;//记录每层的最多能容纳的节点数量(第一层最多为1)
for(int i = 0; i < count.size(); ++i){
if(count[i] > maxNumOfNode){//该高度对应的节点数超过二叉树容纳量
flag = 1;
break;
}
if(count[i] < maxNumOfNode){
//这一层可以容纳maxNmOfNode个节点,而节点数有count[i]个,种类数相当于组合数
//从maxNumOfNode个位置中,选出count[i]个来
res = (res * c[maxNumOfNode][count[i]]) % MOD;
}
//当count[i] == maxNumOfNode,说明该层满载,不会对二叉树种数做出贡献
maxNumOfNode = count[i] * 2;//下一层最多容纳节点数量等于该层节点数量 * 2
}
if(!flag){
res = res % (1000000000 + 7);
cout << res << endl;
} else cout << 0 << endl;//二叉树为0种
return 0;
}
Q3
感觉题目并没有说清楚会不会自动下落之类的。。。
下面的代码是错的
#include <iostream>
#include <vector>
#include <string>
#include "limits.h"
#include <algorithm>
using namespace std;
int main() {
string frame, brick;
cin >> frame >> brick;
int len1 = frame.size(), len2 = brick.size();
int res = INT_MAX;
//暴力模拟,brick在frame上面滑动
for(int i = 0; i <= len1 - len2; ++i){//i相当于两个数组之间的偏置
string tmp = frame;
for(int j = 0; j < len2; ++j) tmp[i+j] += (brick[j] - '0'); //累加值
int max_v = *max_element(tmp.begin(), tmp.end());
int min_v = *min_element(tmp.begin(), tmp.end());
res = min(res, max_v - min_v);
}
cout << res << endl;
return 0;
}
不知道有没有人有比较好的解法