得物笔试 得物笔试题 0507

笔试时间:2025年5月7日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题

n 个有礼貌的人正排好队(初始顺序为1 ~ n)准备依次通过 m, 个门,门的类型有 A、 B两种。通过这两种门时,这n 个人的顺序会发生变化,变化规则如下:A型门:走到这种门前,第一个人会有礼貌的拉开门,等到其余所有人都通过后,自己最后通过。队列中其余人的顺序不变。B型门:走到这种门前,第一个人会让给第二个人进,第二个人会让给第三个人进,以此类推。到最后,一开始排在队列的第一个人变成了最后一个进门的,一开始排在队列的最后一个人变成了第一个进门的。

输入描述

第一行输入一个正整数n,代表一共有多少人。

第二行输入一个非负整数 m,代表一共有几扇门。

接下来输入 m行数据,在 m行中的第i行输入一个字符A或者 B,代表第i扇门的类型。

输出描述

在一行中以空格分隔输出通过 m 扇门后,这些人的排列顺序

样例输入

5

4

A

A

B

A

样例输出

1

5

4

3

2

参考题解

使用一个双端队列(Deque)来模拟队伍。

对于操作 'A'(队首到队尾),根据当前队伍是否被逻辑反转,将元素从队列的一端移到另一端。

对于操作 'B'(反转),不实际移动元素,而是用一个布尔标志位来记录队伍的“观察方向”是否反转。

最后根据这个标志位,决定是正序还是逆序输出队列中的元素。

C++:

// C++ 版本

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

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;

    deque<int> dq;
    for(int i = 1; i <= n; i++){
        dq.push_back(i);
    }

    bool isReversed = false;
    for(int k = 0; k < m; k++){
        string op;
        cin >> op;
        if(op == "A"){
            if(!isReversed){
                int v = dq.front();
                dq.pop_front();
                dq.push_back(v);
            } else {
                int v = dq.back();
                dq.pop_back();
                dq.push_front(v);
            }
        } else { // op == "B"
            isReversed = !isReversed;
        }
    }

    if(!isReversed){
        for(size_t i = 0; i < dq.size(); i++){
            cout << dq[i] << "\n";
        }
    } else {
        for(auto it = dq.rbegin(); it != dq.rend(); ++it){
            cout << *it << "\n";
        }
    }

    return 0;
}

Java:

import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
   public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);
       int n = sc.nextInt();
       int m = sc.nextInt();

       Deque<Integer> dq = new LinkedList<>();
       for (int i = 1; i <= n; i++) {
           dq.addLast(i);
       }

       boolean isReversed = false;

       for (int k = 0; k < m; k++) {
           String op = sc.next();

           if (op.equals("A")) {
               if (!isReversed) {
                   int val = dq.removeFirst();
                   dq.addLast(val);
               } else {
                   int val = dq.removeLast();
                   dq.addFirst(val);
               }
           } else { // op.equals("B")
               isReversed = !isReversed;
           }
       }

       StringBuilder resultBuilder = new StringBuilder();
       if (n > 0) { // n is guaranteed to be >= 1 by constraints
           if (!isReversed) {
               Iterator<Integer> iterator = dq.iterator();
               resultBuilder.append(iterator.next()); // First element
               while (iterator.hasNext()) {
                   resultBuilder.append("\n").append(iterator.next());
               }
           } else {
               Iterator<Integer> descendingIterator = dq.descendingIterator();
               resultBuilder.append(descendingIterator.next()); // First element from reversed perspective
               while (descendingIterator.hasNext()) {
                   resultBuilder.append("\n").append(descendingIterator.next());
               }
           }
       }
       System.out.println(resultBuilder.toString());
       sc.close();
   }
}

Python:

# Python 版本

import sys
from collections import deque

def main():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    m = int(next(it))

    dq = deque(range(1, n+1))
    is_reversed = False

    for _ in range(m):
        op = next(it)
        if op == "A":
            if not is_reversed:
                dq.append(dq.popleft())
            else:
                dq.appendleft(dq.pop())
        else:  # op == "B"
            is_reversed = not is_reversed

    out = []
    if not is_reversed:
        out.extend(str(x) for x in dq)
    else:
        out.extend(str(x) for x in reversed(dq))

    sys.stdout.write("\n".join(out))

if __name__ == "__main__":
    main()

第二题

小牛拥有一个魔法,可以对一个正整数a的十进制数字进行任意重新排列。随后,他将排列后的数字序列分成b段,形成b个子数字。具体地要求如下:  每一段必须是排列后数字序列中的连续子串,b段连起来恰好能够完整的拼回重新排列后的数字a‘不得遗漏或重叠。每一段至少包含1位数字(即不能出现空段);允许某段生成的子数字为0,但不允许出现多余的前导零。请你求出分成b段后,这b个子数之和的最大可能值。

【名词解释】连续子串为从原数字序列中,连续的选择一段数位(可以全选)得到的新字符串。除整数0外,任何以0开头的多位数字的的首个0,都叫做多余的前导零。例如,01中的0是多余的前导零,而 101 中的 0不是前导零。0 本身没有多余的前导零。

输入描述

在一行上输入两个整数 a,b,分别表示原始整数与分段数。

b范围的意义是:保证b不超过整数 a 的十进制长度。

输出描述

输出一个整数,表示将整数 a 的数字打乱顺序后分为b段所得各子数之和的最大值。

样例输入

13 1

样例输出

31

参考题解

将输入整数 a 的各位数字提取出来,并按降序排列,形成一个新的数字字符串。这是因为要使得分割后的数字之和最大,通常将较大的数字放在高位或独立成较大的数。使用动态规划。定义 dp[i][j] 表示将排序后数字字符串的前 i 个字符分割成 j 段所能得到的最大和。遍历所有可能的分割点和段数,通过 dp[i][j] = max(dp[k][j-1] + value(substring(k, i))) 来更新 dp 表,其中 value(substring(k, i)) 是从第 k 个字符到第 i-1 个字符组成的子数字串的值(注意处理前导零)。最终结果为 dp[length_of_string][b]。

C++:

// C++ 版本

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

long long parseValue(const string &s) {
    // 去掉多余前导零
    int i = 0, n = s.size();
    if (n > 1 && s[0] == '0') {
        while (i < n - 1 && s[i] == '0') i++;
    }
    return stoll(s.substr(i));
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    long long a_val;
    int b_segments;
    cin >> a_val >> b_segments;

    string s = to_string(a_val);
    sort(s.begin(), s.end());
    // 逆序得到最终字符串
    reverse(s.begin(), s.end());
    int n_len = s.size();

    const long long NEG_INF = LLONG_MIN / 4;
    vector<vector<long long>> dp(n_len + 1, vector<long long>(b_segments + 1, NEG_INF));
    dp[0][0] = 0;

    for (int k = 1; k <= b_segments; k++) {
        for (int i = k; i <= n_len; i++) {
            long long best = NEG_INF;
            for (int p = k - 1; p < i; p++) {
                long long prev = dp[p][k - 1];
                if (prev > NEG_INF / 2) {
                    string segment = s.substr(p, i - p);
                    long long val = parseValue(segment);
                    best = max(best, prev + val);
                }
            }
            dp[i][k] = best;
        }
    }

    cout << dp[n_len][b_segments] << "\n";
    return 0;
}

Java:

import java.util.Arrays;
import java.util.Scanner;

public class Main {

   private static long parseValue(String s) {
       if (s.length() > 1 && s.charAt(0) == '0') {
           int i = 0;
           while (i < s.length() - 1 && s.charAt(i) == '0') {
               i++;
           }
           return Long.parseLong(s.substring(i));
       }
       return Long.parseLong(s);
   }

   public static void main(String[] args) {
       Scanner scanner = new Scanner(System.in);
       long a_val = scanner.nextLong();
  

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

门口唉提是地铁杀:之前b站被一个游戏demo深深的吸引了。看up主页发现是个初创公司,而且还在招人,也是一天60。二面的时候要我做一个登录验证和传输文件两个微服务,做完要我推到github仓库,还要我加上jaeger和一堆运维工具做性能测试并且面试的时候投屏演示。我傻乎乎的做完以后人家跟我说一句现在暂时不招人,1分钱没拿到全是白干
你的秋招第一场笔试是哪家
点赞 评论 收藏
分享
uu们,拒offer时hr很生气怎么办我哭死
爱睡觉的冰箱哥:人家回收你的offer,或者oc后没给你发offer的时候可不会愧疚你,所以你拒了也没必要愧疚他。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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