【秋招笔试】2025.09.13京东秋招真题改编

✅ 秋招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题
  • 对照解析查漏补缺

🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。

🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力

🌸 目前本专栏已经上线180+套真题改编解析,后续会持续更新的

春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗

京东

题目一:音响系统优化问题

1️⃣:二分答案,枚举最大音量差值

2️⃣:对于固定的差值,使用双向贪心算法验证可行性

3️⃣:计算前缀和后缀约束,取最大值确定最终音量配置

难度:中等

这道题目的核心思想是二分答案配合贪心验证。通过固定最大差值,可以将问题转化为判定性问题。关键在于理解双向约束的贪心策略:从左到右和从右到左分别计算每个位置的最小值约束,然后取两者的最大值。时间复杂度为 O(n log V),其中 V 是数值范围。

题目二:智能锁密码验证问题

1️⃣:预处理所有位置的约束条件,检查是否存在冲突

2️⃣:使用数位DP,维护当前前缀与上限相等/小于的状态

3️⃣:逐位转移,同时满足约束条件和数值上界限制

难度:中等偏难

这道题目是经典的数位DP问题,需要在满足特定位约束的前提下统计不超过给定上限的数的个数。核心技巧是维护两个状态:当前数与上限相等的方案数和已经小于上限的方案数。通过逐位枚举并检查约束条件,可以高效地统计所有合法方案。时间复杂度为 O(L),其中 L 是二进制位数。

01. 音响系统优化问题

问题描述

小毛是一位音响工程师,负责调试一套由 个音响组成的环绕音响系统。每个音响都有一个音量等级 ,但由于设备老化,相邻音响的音量差异过大会产生不和谐的音效。

为了改善音质,小毛可以对任意音响进行最多 次音量提升操作,每次操作可以将某个音响的音量等级增加 。同一个音响可以被多次调节。

小毛希望通过这些操作,使得相邻音响之间音量差的绝对值的最大值尽可能小,从而获得最佳的音响效果。

输入格式

输入包括多组测试数据。

第一行有一个正整数 ),表示测试数据的组数。

对于每组测试数据:

第一行有两个正整数 )和 ),分别表示音响数量和最多可以执行的音量提升次数。

第二行有 个正整数 ),表示每个音响当前的音量等级。

输出格式

对于每组测试数据,输出一个正整数,表示经过操作后相邻音响音量差绝对值的最大值最小是多少。

样例输入

1
5 3
3 1 5 4 1

样例输出

2
样例 解释说明
样例1 对第2个音响执行2次音量提升(1→3),对第5个音响执行1次音量提升(1→2),得到新的音量等级 。相邻音响音量差的绝对值分别为 $

数据范围

题解

这道题的关键思路是二分答案。对于一个给定的最大差值 ,可以检查是否能够通过不超过 次操作使得所有相邻音响的音量差不超过

具体来说,如果我们固定最大差值为 ,那么对于每个位置 ,调整后的音量 需要满足:

  1. (音量只能增加,不能减少)
  2. (相邻音响音量差不超过
  3. (总的音量提升次数不超过

检查函数的实现:

  1. 从左到右计算前缀下界:
  2. 从右到左计算后缀下界:
  3. ,这样可以保证相邻差值不超过
  4. 统计总操作次数 ,检查是否不超过

二分的范围是 ,每次检查的时间复杂度是 ,所以总时间复杂度是 ,其中 是数值的最大值。

参考代码

  • Python
import sys
input = lambda: sys.stdin.readline().strip()

def check(arr, k, max_diff):
    """检查在最大差值为max_diff的约束下,是否能用不超过k次操作完成"""
    n = len(arr)
    
    # 从左到右计算前缀下界
    left_bound = [0] * n
    left_bound[0] = arr[0]
    for i in range(1, n):
        left_bound[i] = max(arr[i], left_bound[i-1] - max_diff)
    
    # 从右到左计算后缀下界
    right_bound = [0] * n
    right_bound[n-1] = arr[n-1]
    for i in range(n-2, -1, -1):
        right_bound[i] = max(arr[i], right_bound[i+1] - max_diff)
    
    # 计算最终音量和所需操作次数
    total_ops = 0
    for i in range(n):
        final_vol = max(left_bound[i], right_bound[i])
        total_ops += final_vol - arr[i]
        if total_ops > k:  # 提前终止
            return False
    
    return total_ops <= k

def solve():
    t = int(input())
    for _ in range(t):
        n, k = map(int, input().split())
        arr = list(map(int, input().split()))
        
        # 二分答案
        left, right = 0, 10**9
        result = right
        
        while left <= right:
            mid = (left + right) // 2
            if check(arr, k, mid):
                result = mid
                right = mid - 1
            else:
                left = mid + 1
        
        print(result)

solve()
  • Cpp
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

bool canAchieve(const vector<ll>& a, ll k, ll maxDiff) {
    int n = a.size();
    vector<ll> leftMin(n), rightMin(n);
    
    // 计算从左到右的最小值约束
    leftMin[0] = a[0];
    for (int i = 1; i < n; i++) {
        leftMin[i] = max(a[i], leftMin[i-1] - maxDiff);
    }
    
    // 计算从右到左的最小值约束
    rightMin[n-1] = a[n-1];
    for (int i = n-2; i >= 0; i--) {
        rightMin[i] = max(a[i], rightMin[i+1] - maxDiff);
    }
    
    // 计算总的操作次数
    ll totalInc = 0;
    for (int i = 0; i < n; i++) {
        ll finalVal = max(leftMin[i], rightMin[i]);
        totalInc += finalVal - a[i];
        if (totalInc > k) return false;  // 提前退出
    }
    
    return totalInc <= k;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t;
    cin >> t;
    
    while (t--) {
        int n;
        ll k;
        cin >> n >> k;
        
        vector<ll> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        
        // 二分查找最小的最大差值
        ll left = 0, right = 1e9;
        ll ans = right;
        
        while (left <= right) {
            ll mid = (left + right) / 2;
            if (canAchieve(a, k, mid)) {
                ans = mid;
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        
        cout << ans << "\n";
    }
    
    return 0;
}
  • Java
import java.util.*;
import java.io.*;

public class Main {
    
    // 检查在最大差值为maxDiff的约束下,是否能用不超过k次操作完成
    static boolean canSolve(long[] a, long k, long maxDiff) {
        int n = a.length;
        long[] leftBnd = new long[n];
        long[] rightBnd = new long[n];
        
        // 从左到右计算最小值约束
        leftBnd[0] = a[0];
        for (int i = 1; i < n; i++) {
            leftBnd[i] = Math.max(a[i], leftBnd[i-1] - maxDiff);
        }
        
        // 从右到左计算最小值约束
        rightBnd[n-1] = a[n-1];
        for (int i = n-2; i >= 0; i--) {
            rightBnd[i] = Math.max(a[i], rightBnd[i+1] - maxDiff);
        }
        
        // 计算总操作次数
        long totalOps = 0;
        for (int i = 0; i < n; i++) {
            long finalValue = Math.max(leftBnd[i], rightBnd[i]);
            totalOps += finalValue - a[i];
            if (totalOps > k) return false;  // 提前返回
        }
        
        return totalOps <= k;
    }
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = 

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

互联网刷题笔试宝典 文章被收录于专栏

互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

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