百度正式批笔经(研发A卷,算法题解+AK代码)

笔试:2022.09.13
岗位:c++研发工程师
时长:2小时(实际完成1小时)
在牛客上进行

经验教训:
一定要带好纸和笔!!!(全程无纸笔,只能痛苦乱答了)

单选题+多选题,八股知识

算法题

题目1

题面

判断一个长字符串,包含几个“baidu”型字符子串。”baidu”型字符串定义为,长度为5的字符串,任意两个字符不同,且第一第四位是辅音字母,另外三位是元音字母。字符串长度为20万。

思路

看清题意,暴力判断就行了

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>

using namespace std;

string s;

bool check(const char &ch) {
    if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
        return true;
    return false;
}

int main() {
    cin >> s;
    int n = s.size();
    int ans = 0;
    for (int i = 0; i < n - 4; ++i) {
        bool flag = 1;
        if (check(s[i]) || check(s[i+3]) || !check(s[i+1]) || !check(s[i+2]) || !check(s[i+4])) 
            continue;
        for (int j = 0; j < 5; ++j)
            for (int k = j + 1; k < 5; ++k)
                if (s[i+j] == s[i+k])
                    flag = 0;
        ans += flag;   
    }
    cout << ans <<endl;
    return 0;
}

题目2

给q个字符串,每个字符串包含01。一个字符串能翻转任意次,每次翻转相邻两个数。求这q个字符串,能否变为全0或全1。字符串总长度20万。

思路

蛮有意思的题目,分享两个做法。

第一个做法:找规律

假设我们把所有相邻的1都变成0,其他1都是孤立的,可以全部交换到队列开头,那么只要判断奇偶,就知道是否能全部变成0。
做法很简单,只要对整个序列求一遍异或和即可。
(考场我只想到了这里,提交后只有10分)
但是这样可能有问题,比如010,它的最终答案是全1的,不能变成全0。
怎么办呢,把01交换,重新跑一遍。两次只要有一次是Yes,答案就是Yes。

第二个做法:动态规划

考虑到交换只能是相邻的,也就是我们当前是否交换只和上一个状态有关,很自然地想到用动态规划。
只有上一个状态,不好转移,还要考虑前面是变成了全0或者全1。
我设置了4个状态
f[i][0][0]表示最后一位为0,前面i-1位均为0,是否有解
f[i][0][1]表示最后一位为0,前面i-1位均为1,是否有解
f[i][1][0]表示最后一位为1,前面i-1位均为0,是否有解
f[i][1][1]表示最后一位为1,前面i-1位均为1,是否有解
每步的转移其实就两种情况,i翻转或者不翻转,所以有8个转移方程,具体看代码。
最终当f[n-1][0][0]为true,或者f[n-1][1][1]为true,即为Yes。

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>

using namespace std;

string s;
bool f[200005][2][2];

int main() {
    int q;
    cin >> q;
    while (q--) {
        cin >> s;
        int n = s.size();
        if (s[0] == '0') {
            f[0][0][0] = f[0][0][1] = true;
            f[0][1][0] = f[0][1][1] = false;
        }
        else {
            f[0][0][0] = f[0][0][1] = false;
            f[0][1][0] = f[0][1][1] = true;
        }
        for (int i = 1; i < n; ++i) {
            f[i][0][0] = f[i][0][1] = f[i][1][0] = f[i][1][1] = false;
            if (s[i] == '0') {
                f[i][0][0] |= f[i-1][0][0];
                f[i][0][1] |= f[i-1][1][1];
                f[i][1][0] |= f[i-1][1][0];
                f[i][1][1] |= f[i-1][0][1];
            }
            else {
                f[i][0][0] |= f[i-1][1][0];
                f[i][0][1] |= f[i-1][0][1];
                f[i][1][0] |= f[i-1][0][0];
                f[i][1][1] |= f[i-1][1][1];
            }
        }
        if (f[n-1][0][0] || f[n-1][1][1])
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
    return 0;
}

题目3

N*M的字符矩阵,包含red三个字母。有三条路是不能走的,”r->d”,”e->r”,”d->e”。求左上角到右下角的最段路。

思路

带障碍的,边权为1的最短路。
经典BFS(宽度优先搜索问题)

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>

using namespace std;

int n, m;
char A[505][505];
int Q[2500005][2], dis[505][505];

const int fx[4] = {0, 1, -1, 0};
const int fy[4] = {1, 0, 0, -1};

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
            scanf(" %c", &A[i][j]);
            dis[i][j] = 1e9;
        }
    int l = 0, r = 1;
    Q[0][0] = 0, Q[0][1] = 0; dis[0][0] = 0;
    while (l < r) {
        for (int t = 0; t < 4; ++t) {
            int ux = Q[l][0];
            int uy = Q[l][1];
            int tx = ux + fx[t];
            int ty = uy + fy[t];
            if (tx < 0 || tx >= n || ty < 0 || ty >= m)
                continue;
            if ((A[ux][uy] == 'r' && A[tx][ty] == 'd') || 
                (A[ux][uy] == 'e' && A[tx][ty] == 'r') || 
                (A[ux][uy] == 'd' && A[tx][ty] == 'e')) 
                continue;
            if (dis[tx][ty] > dis[ux][uy] + 1) {
                dis[tx][ty] = dis[ux][uy] + 1;
                Q[r][0] = tx; Q[r][1] = ty;
                r++;
            }
        }
        l++;
    }
    if (dis[n-1][m-1] == 1e9)
        cout << -1;
    else
        cout << dis[n-1][m-1];
    return 0;
}

八股完成总时长:20分钟;
算法题完成总时长:40分钟;
得分100+100+100=300。

算法不难,八股比较难。
希望百度还有HC给正式批的笔试同学哈哈~

#秋招##校招##百度##笔经##百度23秋招笔试编程题有点儿简单啊#
全部评论
第二题好像可以判断0 1的个数是否都是奇数 都是奇数就是No
2 回复 分享
发布于 2022-09-13 21:28 北京
第二题分析一下就知道每次变换,要么0和1的个数不变,要么0或者1的个数加2。直接判断奇偶数就行了
1 回复 分享
发布于 2022-09-14 15:08 湖北

相关推荐

点赞 评论 收藏
分享
10-24 13:36
门头沟学院 Java
Zzzzoooo:更新:今天下午有hr联系我去不去客户端,拒了
点赞 评论 收藏
分享
点赞 评论 收藏
分享
15 42 评论
分享
牛客网
牛客企业服务