8.19 hw笔试题

牛客上看到别人分享的题目8月19日华为笔试题_技术交流_牛客网

Q1

给你N行M列的人,他们是一个方阵。左上角是(0,0),右下角是(n-1, m-1),最外圈的人顺时针报数,当他们报的数个位是7并且十位是奇数,就选出来。外圈报完了内圈接着报,一直到所有人都报完,问最后选出来的是哪些。

要求是10<=n,m<=1000,如果输入不合法,那么就是返回空数组

类似54. 螺旋矩阵 - 力扣(LeetCode)

自己写了一下,如果理解怎么顺时针遍历的话,这题就很好处理,注意边界的处理以及坐标的存储就行

#include 
#include 
#include 

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> 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

组合计算:
8.19 hw笔试题_第1张图片

给你N个节点,然后输入他们所在的高度,问最后的二叉树可以有几种,结果可能很大,对10^9+7取模
0

这个代码好像处理大数是有问题的:如果在循环内乘法就已经溢出的话,循环外的取模也会出错,好像是要用到:lucas(数论定理)_百度百科,反正我是不懂。。

#include 
#include 
#include 

using namespace std;

int main(){
    int n;
    cin >> n;//输入节点个数
    if(n <= 0 || n > 1000){//边界判断
        cout << 0 << endl;
        return 0;
    }
    vector v(n, 0);//节点的高度
    for(int i = 0; i < n; ++i)  cin >> v[i];//输入每个节点对应高度
    sort(v.begin(), v.end());
    int maxHeight = v.back();
    vector 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 
#include 
#include 
#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 v(n, 0);//节点的高度
    for(int i = 0; i < n; ++i)  cin >> v[i];//输入每个节点对应高度
    sort(v.begin(), v.end());
    int maxHeight = v.back();//最大高度
    vector 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 
#include 
#include 
#include "limits.h"
#include 

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;
}

不知道有没有人有比较好的解法

你可能感兴趣的:(8.19 hw笔试题)