小红书笔试 小红书笔试题 0813

笔试时间:2025年8月13日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:超级重排

Tk 有一个长度为 n 的数组{a1,a2,...,an}。Tk 定义这个数组的权值为:\sum_{i=1}^{n} a_i。为了使数组的权值最大,Tk 提出如下超级重排流程:·将所有元素的十进制表示按原序拼接成一个字符串;·对该字符串中的所有字符进行重新排列;·按照原元素的位数切分字符串,恢复为 n 个新数字。或者换句话说,首先,收集所有数字的每一个单独的数位;其次,对于每一个原始数字 ai,记录下它的位数。你必须用收集到的所有数位来构造 n 个新的数字,其中第 j 个新数字的位数必须与原始数组中第 j 个数字 aj 的位数相同。你的目标是找到一种分配这些数位的方式,使得这 n 个新数字的总和达到最大。

输入描述

第一行输入一个整数 n(1≤n≤2*105),表示数组长度。

第二行输入 n 个整数a1,a2,...,an(1≤ai≤109)表示数组 a,题目保证每个元素的十进制表示中不含字符 '0'

输出描述

输出一个整数,表示经过超级重排后数组的最大权值。

样例输入

2

36 15

样例输出

114

参考题解

每个位置的权重是 10^e,其中 e 是它到右端的距离(个位 e=0,十位 e=1,百位 e=2…)。所有数字的位数是固定的,所以每个原数字的高位权重大,低位权重小。最优策略:把所有位置(带权重的格子)统一考虑,按权重从大到小分配最大的数字(重排不等式)。记录位数统计每个 ai 的位数 Li。统计所有数字字符例如 [36,15] [36, 15] [36,15] → [3, 6, 1, 5]。统计每个位置的权重如果一个数字的长度是 L,它的位权分别是:10^{L-1}, 10^{L-2}, ....., 10^0把所有数字的位权放到一个“权重桶”里。排序匹配将权重从大到小排序。将数字字符从大到小排序。一一对应,最大数字放到最大权重位置。计算总和不需要真正构造新数字,只要累加:贡献=数字×位权。

C++:

#include <bits/stdc++.h>
#include <boost/multiprecision/cpp_int.hpp>
using namespace std;
using boost::multiprecision::cpp_int;

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

    int n;
    if (!(cin >> n)) return 0;
    if (n <= 0) { cout << 0 << "\n"; return 0; }

    vector<string> tokens;
    tokens.reserve(n);
    for (int i = 0; i < n; ++i) {
        string tok; cin >> tok;
        tokens.push_back(tok);
    }

    int maxL = 0;
    vector<long long> digit_cnt(10, 0);
    vector<int> lens; lens.reserve(n);
    for (auto &tok : tokens) {
        int L = (int)tok.size();
        lens.push_back(L);
        maxL = max(maxL, L);
        for (char ch : tok) {
            int d = ch - '0';
            ++digit_cnt[d];
        }
    }

    // len_cnt[L] = count of tokens with length == L
    vector<long long> len_cnt(maxL + 1, 0);
    for (int L : lens) ++len_cnt[L];

    // suff_ge[L] = number of tokens with length >= L
    vector<long long> suff_ge(maxL + 2, 0);
    long long s = 0;
    for (int L = maxL; L >= 1; --L) {
        s += len_cnt[L];
        suff_ge[L] = s;
    }

    // pow10[e] = 10^e (big integer)
    vector<cpp_int> pow10(maxL > 0 ? maxL : 1);
    pow10[0] = 1;
    for (int e = 1; e < maxL; ++e) pow10[e] = pow10[e - 1] * 10;

    cpp_int ans = 0;
    int d = 9;
    for (int e = maxL - 1; e >= 0; --e) {
        long long slots = suff_ge[e + 1];
        while (slots > 0) {
            while (d >= 0 && digit_cnt[d] == 0) --d;
            if (d < 0) break;
            long long take = (long long)min<long long>(digit_cnt[d], slots);
            // ans += take * d * 10^e
            cpp_int contrib = pow10[e] * (long long)d * take;
            ans += contrib;
            digit_cnt[d] -= take;
            slots -= take;
        }
    }

    cout << ans << "\n";
    return 0;
}

Java:

import java.io.*;
import java.math.BigInteger;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        line = br.readLine();
        if (line == null || line.trim().isEmpty()) {
            System.out.println(0);
            return;
        }
        int n = Integer.parseInt(line.trim());
        if (n <= 0) {
            System.out.println(0);
            return;
        }

        StringTokenizer st = new StringTokenizer("");
        String[] tokens = new String[n];
        int got = 0;
        while (got < n) {
            if (!st.hasMoreTokens()) {
                String l = br.readLine();
                if (l == null) break;
                st = new StringTokenizer(l);
                continue;
            }
            tokens[got++] = st.nextToken();
        }
        if (got < n) { // 输入不足时按 0 处理
            System.out.println(0);
            return;
        }

        int maxL = 0;
        long[] digitCnt = new long[10];
        int[] lens = new int[n];
        for (int i = 0; i < n; i++) {
            String tok = tokens[i];
            int L = tok.length();
            lens[i] = L;
            if (L > maxL) maxL = L;
            for (int k = 0; k < L; k++) {
                int d = tok.charAt(k) - '0';
                digitCnt[d]++;
            }
        }

        long[] lenCnt = new long[maxL + 1];
        for (int L : lens) lenCnt[L]++;

        long[] suffGe = new long[maxL + 2];
        long s = 0;
        for (int L = maxL; L >= 1; L--) {
            s += lenCnt[L];
            suffGe[L] = s;
        }

        BigInteger[] pow10 = new BigInteger[Math.max(1, maxL)];
        pow10[0] = BigInteger.ONE;
        for (int e = 1; e < maxL; e++) {
            pow10[e] = pow10[e - 1].multiply(BigInteger.TEN);
        }

        BigInteger ans = BigInteger.ZERO;
        int d = 9;
        for (int e = maxL - 1; e >= 0; e--) {
            long slots = suffGe[e + 1];
            while (slots > 0) {
                while (d >= 0 && digitCnt[d] == 0) d--;
                if (d < 0) break;
                long take = Math.min(digitCnt[d], slots);
                BigInteger contrib = pow10[e]
                        .multiply(BigInteger.valueOf(d))
                        .multiply(BigInteger.valueOf(take));
                ans = ans.add(contrib);
                digitCnt[d] -= take;
                slots -= take;
            }
        }

        System.out.println(ans.toString());
    }
}

Python:

def main():
    n = int(input())
    tokens = input().split()
    maxL = 0
    len_cnt = [0] * 11
    digit_cnt = [0] * 10
    for tok in tokens:
        L = len(tok)
        len_cnt[L] += 1
        if L > maxL:
            maxL = L
        for ch in tok:
            d = int(ch)
            digit_cnt[d] += 1
    suff_ge = [0] * (maxL + 2)
    s = 0
    for L in range(maxL, 0, -1):
        s += len_cnt[L]
        suff_ge[L] = s
    pow10 = [1] 

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

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

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

全部评论

相关推荐

总结:留了70分钟做编程第三题还是做不来💻题目:&nbsp;选择题20道(50分),编程题3道(10,15,25)❓第一题:排序后遍历一个一个删就行,O(nlogn)t&nbsp;=&nbsp;int(input())for&nbsp;_&nbsp;in&nbsp;range(t):n,&nbsp;d&nbsp;=&nbsp;map(int,&nbsp;input().split())nums&nbsp;=&nbsp;list(map(int,&nbsp;input().split()))nums.sort()&nbsp;//排序if&nbsp;n&nbsp;==&nbsp;1:print(n)else:i,&nbsp;j&nbsp;=&nbsp;0,&nbsp;1del_num&nbsp;=&nbsp;0while&nbsp;i&nbsp;&lt;&nbsp;n&nbsp;and&nbsp;j&nbsp;&lt;&nbsp;n:if&nbsp;nums[j]&nbsp;-&nbsp;nums[i]&nbsp;&lt;=&nbsp;d:del_num&nbsp;+=&nbsp;1j&nbsp;+=&nbsp;1else:i&nbsp;=&nbsp;jj&nbsp;+=&nbsp;1if&nbsp;del_num&nbsp;%&nbsp;2&nbsp;==&nbsp;1:&nbsp;//凑整del_num&nbsp;+=&nbsp;1print(n&nbsp;-&nbsp;del_num)❓第二题:第一个字符作为最后留下来的参考,后面和第一个字符不一样的都会被删,而且可以删去其后和第一个字符一样的字符,O(n)n&nbsp;=&nbsp;int(input())s&nbsp;=&nbsp;input()del_cnt&nbsp;=&nbsp;0ref&nbsp;=&nbsp;s[0]i&nbsp;=&nbsp;1while&nbsp;s[i]&nbsp;==&nbsp;ref:i&nbsp;+=&nbsp;1start&nbsp;=&nbsp;iack&nbsp;=&nbsp;0&nbsp;//&nbsp;类似攻击力for&nbsp;i&nbsp;in&nbsp;range(start,&nbsp;n):if&nbsp;s[i]&nbsp;!=&nbsp;ref:ack&nbsp;+=&nbsp;1&nbsp;//可以评论后面的(攻击后面的)del_cnt&nbsp;+=&nbsp;1&nbsp;//不一样的会被删(被评论)else:if&nbsp;ack&nbsp;&gt;&nbsp;0:ack&nbsp;-=&nbsp;1&nbsp;//&nbsp;被攻击就会被删del_cnt&nbsp;+=&nbsp;1print(del_cnt)❓第三题:不会,O(n^2)只有9%
投递小红书等公司10个岗位
点赞 评论 收藏
分享
15道选择题+3道sql题,没想象中的难
投递拼多多集团-PDD等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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