美团笔试 - 技术方向 0322 题解

T1

求完全由轴对称字母 AHIMOTUVWXY 构成的回文串数量。

  • 数据范围 ,直接 暴力枚举区间判断。
  • 按非轴对称字母分段,每一段单独 manacher 统计回文串数量,
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
char s[N];
set<char> st = {'A', 'H', 'I', 'M', 'O', 'T', 'U', 'V', 'W', 'X', 'Y'};
int main() {
    scanf("%s", s + 1);
    int n = strlen(s + 1), cnt = 0;
    for (int l = 2; l <= n; ++l) {
        for (int i = 1; i + l - 1 <= n; ++i) {
            int f = 1;
            for (int j = 1; j <= l; ++j)
                if (!st.count(s[i + j - 1])) {
                    f = 0;
                    break;
                }
            if (!f) continue;
            for (int j = 1; j * 2 <= l; ++j)
                if (s[i + j - 1] != s[i + l - j]) {
                    f = 0;
                    break;
                }
            cnt += f;
        }
    }
    printf("%d\n", cnt);
    return 0;
}

T2

给定一个排列 ,求对子区间排序后,子区间中位数位置不变的子区间数量。

枚举中位数的位置,从中间同时向左右扩展,统计比 大/小的数的数量,如果相等,说明当前子区间满足题意, 。由于 ,所以可以通过。

#include <bits/stdc++.h>
using namespace std;
void solve() {
    int n, ans = 0;
    scanf("%d", &n);
    vector<int> a(n);
    for (auto &x : a) scanf("%d", &x);
    for (int i = 0; i < n; ++i) {
        int l = 0, r = -2;
        for (int j = 0; i - j >= 0 && i + j < n; ++j) {
            (a[i - j] < a[i] ? l : r)++;
            (a[i + j] < a[i] ? l : r)++;
            ans += l == r;
        }
    }
    printf("%d\n", ans);
}
int main() {
    int t;
    scanf("%d", &t);
    while (t--) solve();
    return 0;
}

T3

的数轴上,有一个初始位置为 的机器人。给定一个指令序列 ,指令集由 L(向左移动,若在 则不动)、R(向右移动,若在 则不动)以及 ?(随机转为 L 或 R 并移动)组成。问机器人所有可能的最终位置。

  • 注意到,最终的答案一定是形如 ,即一个大区间套小区间,小区间部分答案为 交替,大区间的剩余部分为连续的
  • 维护两个区间的端点 ,其中
  • 不考虑任何冲突,对于每个指令:
    • L :全部左移,即全
    • R :全部右移,即全
    • ?
      • 如果 ,即没有连续 前缀,则同时左移
      • 如果 ,说明存在连续 段,而连续 段会同时向左右两边扩充,即 ,此时 会左移,但是 会右移
      • 对于 的讨论同理。
  • 考虑在什么情况下会产生连续 段:对于 ,情况为 ,即当前指令为 ? ,可以理解为最左边的 再次左移时移出去了,但实际上因为“撞墙”了只能继续留在 ,此时 的情况和 是对称的。
  • 考虑如何处理冲突,定义修正函数
    • 以上操作的执行均满足 的条件,不会产生区间冲突;
    • 区间端点可能超出 :直接对所有区间端点进行修正即可;
    • 可能会出现 段消失, 的情况:直接令 即可。
  • 时间复杂度
  • 特别注意,题目没说 ,虽然样例都是这样的(笔试的时候因为这个卡 卡了一个小时)。
  • 题外话:从笔试题的角度来说,这题确实考得非常难了,而且如果不继续想一下性质,直接用大量 if-else 条件处理所有情况,写起来考虑各种边界条件会非常麻烦。
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    int n, k; string s;
    cin >> n >> k >> s;
    int sL = k, sR = k, L = k, R = k;
    for (auto c : s) {
        switch (c) {
        case 'L':
            --sL, --L, --R, --sR;
            break;
        case 'R':
            ++sL, ++L, ++R, ++sR;
            break;
        default:
            sL < L ? ++L : --L;
            sR > R ? --R : ++R;
            --sL, ++sR;
            break;
        }
        auto f = [&](int &x) {
            x = min(n, max(1, x));
        };
        if (L < 1 && 1 < R) L = 2;
        if (R > n && n > L) R = n - 1;
        f(sL), f(sR), f(L), f(R);
        if (L > R) L = R;
    }
    string ans(n, '0');
    for (int i = sL; i < L; ++i) ++ans[i - 1];
    for (int i = L; i <= R; i += 2) ++ans[i - 1];
    for (int i = R + 1; i <= sR; ++i) ++ans[i - 1];
    cout << ans << '\n';
    return 0;
}

当然,如果你真的想所有情况 if-else 判断一下,这种代码我也有。

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    int n, k; string s;
    cin >> n >> k >> s;
    int L = k, R = k, sL = k, sR = k;
    for (auto c : s) {
        if (c == 'L') {
            if (sL > 1)
                --sL, --L, --R, --sR;
            else if (sL < L)
                --L, --R, --sR;
            else if (L + 1 < R)
                --R, --sR, ++L;
            else if (sR > 1)
                --sR;
        } else if (c == 'R') {
            if (sR < n)
                ++sL, ++L, ++R, ++sR;
            else if (R < sR)
                ++L, ++R, ++sL;
            else if (L + 1 < R)
                ++L, ++sL, --R;
            else if (sL < n)
                ++sL;
        } else {
            if (sL == L && L > 1)
                --L, --sL;
            else if (sL < L)
                sL = max(sL - 1, 1), ++L;
            else if (L < n)
                ++L;
            if (sR == R && R < n)
                ++R, ++sR;
            else if (R < sR)
                sR = min(sR + 1, n), --R;
            else if (R > 1)
                --R;
            L = min(n, max(1, L));
            R = min(n, max(1, R));
            if (L > R)
                L = R;
        }
        // assert(0 <= sL);
        // assert(sL <= L);
        // assert(L <= R);
        // assert(R <= sR);
        // assert(sR < n);
        // printf("%d %d %d %d\n", sL, L, R, sR);
    }
    string ans(n, '0');
    for (int i = sL; i < L; ++i) ans[i - 1] = '1';
    for (int i = L; i <= R; i += 2) ans[i - 1] = '1';
    for (int i = R + 1; i <= sR; ++i) ans[i - 1] = '1';
    cout << ans << '\n';
    return 0;
}

再附赠一个对拍程序。

#include <bits/stdc++.h>

using namespace std;
using ll = long long;
const int N = 1e5 + 5;

string bf(int n, int k, string s) {
    bitset<N> bs;
    bs[k] = 1;

    for (auto c : s) {
        // string ans(n, '0');
        // for (int i = 0; i < n; ++i)
        //     ans[i - 1] = bs[i] + '0';
        // cout << ans << endl;
        int L = bs[1], R = bs[n];
        switch (c) {
        case 'L':
            bs = bs >> 1;
            if (L)
                bs[1] = 1;
            break;
        case 'R':
            bs = bs << 1;
            if (R)
                bs[n] = 1;
            break;
        default:
            bs = (bs << 1) | (bs >> 1);
            if (L)
                bs[1] = 1;
            if (R)
                bs[n] = 1;
            break;
        }
        bs[0] = bs[n + 1] = 0;
    }
    string ans(n, '0');
    for (int i = 1; i <= n; ++i)
        ans[i - 1] += bs[i];
    return ans;
}
string solve1(int n, int k, string s) {
    int L = k, R = k, sL = k, sR = k;
    for (auto c : s) {
        if (c == 'L') {
            if (sL > 1)
                --sL, --L, --R, --sR;
            else if (sL < L)
                --L, --R, --sR;
            else if (L + 1 < R)
                --R, --sR, ++L;
            else if (sR > 1)
                --sR;
        } else if (c == 'R') {
            if (sR < n)
                ++sL, ++L, ++R, ++sR;
            else if (R < sR)
                ++L, ++R, ++sL;
            else if (L + 1 < R)
                ++L, ++sL, --R;
            else if (sL < n)
                ++sL;
        } else {
            if (sL == L && L > 1)
                --L, --sL;
            else if (sL < L)
                sL = max(sL - 1, 1), ++L;
            else if (L < n)
                ++L;
            if (sR == R && R < n)
                ++R, ++sR;
            else if (R < sR)
                sR = min(sR + 1, n), --R;
            else if (R > 1)
                --R;
            L = min(n, max(1, L));
            R = min(n, max(1, R));
            if (L > R)
                L = R;
        }
        // assert(0 <= sL);
        // assert(sL <= L);
        // assert(L <= R);
        // assert(R <= sR);
        // assert(sR < n);
        // printf("%d %d %d %d\n", sL, L, R, sR);
    }
    string ans(n, '0');
    for (int i = sL; i < L; ++i) ans[i - 1] = '1';
    for (int i = L; i <= R; i += 2) ans[i - 1] = '1';
    for (int i = R + 1; i <= sR; ++i) ans[i - 1] = '1';
    return ans;
}
string solve2(int n, int k, string s) {
    // scanf("%d%d%s", &n, &k, s);
    int sL = k, sR = k, L = k, R = k;
    for (auto c : s) {
        switch (c) {
        case 'L':
            --sL, --L, --R, --sR;
            break;
        case 'R':
            ++sL, ++L, ++R, ++sR;
            break;
        default:
            sL < L ? ++L : --L;
            sR > R ? --R : ++R;
            --sL, ++sR;
            break;
        }
        auto f = [&](int &x) { x = min(n, max(1, x)); };
        if (L < 1 && 1 < R) L = 2;
        if (R > n && n > L) R = n - 1;
        f(sL), f(sR), f(L), f(R);
        if (L > R) L = R;
    }
    string ans(n, '0');
    for (int i = sL; i < L; ++i) ++ans[i - 1];
    for (int i = L; i <= R; i += 2) ++ans[i - 1];
    for (int i = R + 1; i <= sR; ++i) ++ans[i - 1];
    return ans;
}
int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    // int n, k;
    // string s;
    // cin >> n >> k >> s;
    // cout << solve2(n, k, s) << endl;
    // return 0;
    // For random number generation
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

    // cout << t << endl;
    auto check = [&](int n, int k, string s) {
        static int tc = 0;
        // For verification: compare bf and solve
        string bf_ans = bf(n, k, s);
        string ans1 = solve1(n, k, s);
        string ans2 = solve2(n, k, s);
        cout << "Test case " << ++tc << ": ";
        if (bf_ans != ans1 || bf_ans != ans2) {
            cout << "Mismatch found!" << endl;
            cout << n << " " << k << endl;
            cout << s << endl;
            cout << "bf: " << bf_ans << endl;
            cout << "solve1: " << ans1 << endl;
            cout << "solve2: " << ans1 << endl;
            exit(0);
        } else {
            cout << "OK" << endl;
        }
    };
    // Number of test cases
    // Generate all possible sequences for small inputs
    function<void(int, int, int, string &, int)> generateAllSequences =
        [&](int n, int k, int len, string &s, int pos) {
            if (pos == len) {
                check(n, k, s);
                return;
            }
            // Try all three possible instructions
            s[pos] = 'L';
            generateAllSequences(n, k, len, s, pos + 1);

            s[pos] = 'R';
            generateAllSequences(n, k, len, s, pos + 1);

            s[pos] = '?';
            generateAllSequences(n, k, len, s, pos + 1);
        };

    // For small values, test all possible combinations
    for (int n = 1; n <= 5; ++n) {
        for (int k = 1; k <= n; ++k) {
            for (int len = 1; len <= 5; ++len) {
                string s(len, ' ');
                generateAllSequences(n, k, len, s, 0);
            }
        }
    }
    int tot = 3000; // You can adjust this
    for (int tc = 0; tc < tot; ++tc) {
        // Generate random n, k and length of string
        int n = rng() % N + 1;   // Random n between 1 and 10^6
        int k = rng() % n + 1;   // Random k between 1 and n
        int len = rng() % N + 1; // Random length between 1 and 10^6

        // Generate random instruction sequence
        string s;
        for (int i = 0; i < len; ++i) {
            int cmd = rng() % 3;
            if (cmd == 0)
                s += 'L';
            else if (cmd == 1)
                s += 'R';
            else
                s += '?';
        }
        check(n, k, s);
    }
    return 0;
}
#笔试##牛客创作赏金赛##美团笔试##美团#
全部评论
请问技术方向的选择题偏向什么内容呀,我看有人说选择题都是大模型的知识点
点赞 回复 分享
发布于 03-28 18:59 上海
acm下场乱杀了
点赞 回复 分享
发布于 03-23 13:27 湖北

相关推荐

头像
08-01 13:10
已编辑
武汉大学 Java
面试官非常普通的进入了面试,对于楼主直球表达的对一面面评的疑惑表示,太底层的东西我们都不问的(???)。1.&nbsp;自我介绍2.&nbsp;tinykv有没有做出突出的优化点(没有)3.&nbsp;tinykv底层用的什么存储,badgerDB,好那你来说一下lsm&nbsp;tree的八股。4.&nbsp;lsm&nbsp;tree胡言乱语几min,楼主也是好久没系统介绍过lsm&nbsp;tree,基本想到啥说啥(读放大、写放大、kv分离、memtable),哪哪都不深入。5.&nbsp;b-tree和b+tree区别,使用场景,继续复读面经(但在复读至跳表时惨遭打断)6.&nbsp;lsm&nbsp;tree相较于b+tree的优势(最传统的ssd优势已经全忘了,吟诵的是方便调参以及更合适云存储场景使用)7.&nbsp;hash冲突怎么解决(参考java,红黑树,还有其他方法,但楼主没复习早忘了)8.&nbsp;hashmap怎么提高并发性能(参考java,分段锁),分几段比较好(不知道,楼主回答跑benchmark一测便知)9.&nbsp;持久化的hashmap怎么在持久化的时候提供服务(楼主回答了双buffer设计,但只记得这个名字,细节早忘了),不用双buffer怎么做(那更是一窍不通)10.&nbsp;面试官表示hashmap都是用mmap的,并且会自动写入磁盘(不懂什么意思,面试官说大家都知道,反正楼主不知道),并且持久化的时候会改一堆的链表,那么假如一个线程在改的过程中寄了导致链表只改了一部分,怎么办?(怎么办,凉拌,毫无思路,说像数据库事务一样整个redolog,楼主自己都觉得性能差)11.&nbsp;编程题:写一个hashmap。楼主写了1h,不是因为难,只是因为菜。12.&nbsp;有什么可以优化点?(楼主绞尽脑汁说了两点,vector预先申请大块空间、链表连续)13.&nbsp;反问:做啥的:非关系型数据库作息:弹性,10点钟下班太晚了(不愧是藤子,至少楼主面的快手/百度/滴滴都表示这个点下班稀松平常)真的不care楼主对高性能存储什么都不懂吗:暧昧的眼神流程几面:3+1面后面聊了些数据库现状,面试官表示时序与对象数据库需求增大,存储行业仍有前景。很普通的二面,虽然很寄,就是很普通的深入到某个点就什么也不会了而已,楼主就这么菜,这点楼主早就知道了。成则称teg深入底层,越老越吃香,可顺利度过35岁危机;败则称teg钱少事多,绩效在集团垫底,就是因为根本没有发财的机会才会越老越吃香。楼主对db没有执念了,不会就是不会,没相关实习就是没相关实习,db不需要楼主这样浅尝辄止的人并非楼主的过错。不许愿三面了,早点挂了投ieg或者wxg去也不失为另一条康庄大道。———————————————挂了,投个sre提前批试试。tx无限复活就是好,每个岗位的面试都能体验一遍。
下一个更好呗:鸡架还是能跑路就跑,特别是数据库中的关系型数据库,2027年要全部国产化,现在基本上都成熟了,ob这些早就霸占市场了,其他db研发团队需求没那么大。
面试问题记录
点赞 评论 收藏
分享
07-30 18:17
已编辑
东莞理工学院 Web前端
字节跳动火山引擎一面46&nbsp;分钟2025.7.151.&nbsp;自我介绍2.&nbsp;介绍项目3.&nbsp;看你项目提到了,cloudflare的全球加速是怎么做的?4.&nbsp;浏览器访问链接全过程5.&nbsp;页面框架加载优化6.&nbsp;跨域是什么7.&nbsp;数组和链表的随机查找、插入删除的时间复杂度的8.&nbsp;MySQL写入锁9.&nbsp;HTTP缓存&nbsp;强缓存&nbsp;协商缓存10.&nbsp;算法题11.&nbsp;反问字节火山引擎二面1.&nbsp;自我介绍2.&nbsp;项目介绍3.&nbsp;项目遇到的性能问题是如何解决的4.&nbsp;css如何实现动画(transition、keyframe)5.&nbsp;如何渲染一万个元素(documentfragment、虚拟列表),同时显示的话呢?(canvas、requestAnimationFrame延迟加载分片渲染)6.&nbsp;算法题:控制并发量7.&nbsp;未来职业发展字节火山引擎三面2025.7.221&nbsp;小时1.&nbsp;请做一个简单的自我介绍。2.&nbsp;之前编程主要是什么方向?是爱好还是认真学习的?3.&nbsp;你更喜欢做前端、全栈还是其他方向?为什么觉得前端可替代性强?4.&nbsp;你平时学习技术的渠道有哪些?5.&nbsp;你现在独立运营两个产品,未来有考虑盈利吗?6.&nbsp;未来的职业发展规划7.&nbsp;请介绍一下你简历里提到的XXX项目,它主要是什么,有哪些难点?8.&nbsp;对于XXX项目中性能优化问题,你解决减少顶点数量的思路是什么?9.&nbsp;提高三维图形真实性的路径精确计算,用到了什么算法?10.&nbsp;在XXX项目中,用&nbsp;WebGL&nbsp;处理时性能瓶颈通常出现在哪些方面,你是如何解决的?11.&nbsp;请介绍一下另一个项目&nbsp;app,它主要功能是什么,如何解决学生无网络时的离线使用问题?12.&nbsp;这个&nbsp;app&nbsp;做了哪些数据分析,还有哪些社交相关功能,自习室排名逻辑是什么?13.&nbsp;这个&nbsp;app&nbsp;如何实现一个账号在多设备同步?14.&nbsp;你做的项目中前端跨端表现好是因为编译成二进制文件和内置运行时,能说说大概流程吗?15.&nbsp;能介绍一下&nbsp;Flutter&nbsp;开发中&nbsp;element&nbsp;和渲染对象相关知识,以及不同端的渲染实现逻辑吗?16.&nbsp;HTTP1.0、HTTP2.0、HTTP3.0&nbsp;有什么区别?17.&nbsp;TCP&nbsp;和&nbsp;UDP&nbsp;有什么区别,Promise&nbsp;有哪三种状态,分别是什么?18.&nbsp;你了解哪些网络安全方面的内容?19.&nbsp;你用到了数据库,能介绍常见数据库类型及大致划分区别吗?20.&nbsp;你提到&nbsp;CDN,能说说&nbsp;CDN&nbsp;加速的原理吗?21.&nbsp;算法题:最长公共子串、二路归并22.&nbsp;你后续的长期规划是继续做技术,还是也会考虑往产品方向发展?23.&nbsp;你未来实习时间大概是怎样的,可以长期实习吗?可以转正吗?24.&nbsp;如果未来做的事情和你自己的规划不太匹配,且全栈机会不多,你会怎么选择?2025.7.30HR&nbsp;反馈:业务说咱们的前端经验和产品sense都很好,但是沟通表达能力相对于另一位同学薄弱了些,并且对于未来规划这部分不太清晰,希望咱们目标可以更坚定一些
点赞 评论 收藏
分享
评论
11
6
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务