美团研发岗 5月9号笔试真题 - 弹性分桶

弹性分桶(Py/Java/C++/Js/Go)题解

美团研发岗 0509笔试 第三题

题目内容

给定nnn个非负整数a1,a2,...,ana_1,a_2,\dots,a_na1,a2,...,an,你可以在分组前对这些数进行任意重排。

你需要把所有数划分到若干个桶,每个桶内包含若干个数,设某个桶内共有ttt个数,桶内最大值为MMM,最小值为mmm,则该桶必须满足:

1 ≤ t ≤ L1 \leq t \leq L1 ≤ t ≤ L

M − m ≤ D + E × (t − 1)M - m \leq D + E \times (t - 1)M − m ≤ D + E × (t − 1)

每个数必须且只能属于一个桶,桶与桶之间互不相交,且并集为全部nnn个数,你的目标是使桶的数量尽可能少,请输出最少桶数。

输入描述

每个测试文件包含多组测试数据,第一行输入一个整数 T(1 ≤ T ≤ 105)T(1 \leq T \leq 10^5)T(1 ≤ T ≤ 105) 表示数据组数,每组测试数据描述如下:

第一行输入四个整数 n, D, E, L(1 ≤ n ≤ 2 × 105, 0 ≤ D, E ≤ 109, 1 ≤ L ≤ n)n, D, E, L(1 \leq n \leq 2 \times 10^5, 0 \leq D, E \leq 10^9, 1 \leq L \leq n)n, D, E, L(1 ≤ n ≤ 2 × 105, 0 ≤ D, E ≤ 109, 1 ≤ L ≤ n)。

第二行输入 nnn 个整数 a1, a2, ..., an(0 ≤ ai ≤ 109)a_1, a_2, \dots, a_n(0 \leq a_i \leq 10^9)a1, a2, ..., an(0 ≤ ai ≤ 109)。

保证所有测试数据的 nnn 之和不超过 2 × 1052 \times 10^52 × 105。

输出描述

对于每组测试数据,输出一行一个整数,表示最少需要多少个桶。

样例1

输入

复制代码
2
7 3 1 3
1 2 3 7 8 10 10
7 0 0 5
5 5 5 6 6 6 6

输出

复制代码
3
2

说明

第一组数据的一个最优划分为1,2,3,7,8,10,10\left1,2,3\\right, \left7,8,10\\right, \left10\\right1,2,3,7,8,10,10,因此答案为333。 第二组数据中由于D=0,E=0D = 0, E = 0D=0,E=0,同一桶内必须全部相等,最少需要222个桶。

题解

思路

贪心 + 双指针

  1. 桶约束只和最大值-最小值元素数量相关
  2. 将桶中元素升序排序,其中a[l]为最小值,a[r]为最大值,其中t = r - l + 1, 上述约束变为t <= L, a[r] - a[l] <= D + E * (t - 1) => a[r] <= a[l] + D + E * (t - 1).可以观察l固定不变情况下,r越大,允许的ar的值也越大。
  3. 想要桶尽可能少=》每个桶装的数量尽可能多,所以可以使用贪心思维尽可能让每个桶装尽可能多元素,不能装时再加入新的桶。具体逻辑为:
    1. 初始对所有元素进行排序
    2. 每一轮尝试新桶时,固定左边解为l = i, 然后根据2不断尝试扩展右边界r当下面某一个条件不满足,加入新的桶重复执行
      • r - l + 1 > L
      • a[r] > a[l] + D + E * (r - i + 1)
  4. 根据3处理之后,可以得到最终桶的数量

C++

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

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

    int T;
    cin >> T;

    while (T--) {
        int n;
        long long D, E;
        int L;
        cin >> n >> D >> E >> L;

        vector<long long> a(n);
        for (auto &x : a) cin >> x;
        // 升序排序
        sort(a.begin(), a.end());

        int ans = 0;
        int i = 0;

        while (i < n) {
            int j = i;

            while (j + 1 < n && (j - i + 1 < L)) {
                long long limit = a[i] + D + E * (j + 1 - i);
                if (a[j + 1] <= limit) j++;
                else break;
            }

            ans++;
            i = j + 1;
        }

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

    return 0;
}

java

java 复制代码
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        int T = Integer.parseInt(br.readLine().trim());

        while (T-- > 0) {
            String[] parts = br.readLine().trim().split(" ");
            int n = Integer.parseInt(parts[0]);
            long D = Long.parseLong(parts[1]);
            long E = Long.parseLong(parts[2]);
            int L = Integer.parseInt(parts[3]);

            long[] a = new long[n];
            String[] arr = br.readLine().trim().split(" ");
            for (int i = 0; i < n; i++) {
                a[i] = Long.parseLong(arr[i]);
            }

            // 升序排序
            Arrays.sort(a);

            int ans = 0;
            int i = 0;

            while (i < n) {
                int j = i;

                while (j + 1 < n && (j - i + 1 < L)) {
                    long limit = a[i] + D + E * (j + 1 - i);
                    if (a[j + 1] <= limit) j++;
                    else break;
                }

                ans++;
                i = j + 1;
            }

            sb.append(ans).append("\n");
        }

        System.out.print(sb.toString());
    }
}

python

python 复制代码
import sys

input = sys.stdin.readline

T = int(input())

for _ in range(T):
    n, D, E, L = map(int, input().split())
    a = list(map(int, input().split()))

    # 升序排序
    a.sort()

    ans = 0
    i = 0

    while i < n:
        j = i

        while j + 1 < n and (j - i + 1 < L):
            limit = a[i] + D + E * (j + 1 - i)
            if a[j + 1] <= limit:
                j += 1
            else:
                break

        ans += 1
        i = j + 1

    print(ans)

javascript

js 复制代码
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on("line", (line) => {
    input.push(line.trim());
});

rl.on("close", () => {
    let idx = 0;
    let T = Number(input[idx++]);

    while (T--) {
        let [n, D, E, L] = input[idx++].split(" ").map(Number);

        let a = input[idx++].split(" ").map(Number);

        // 升序排序
        a.sort((x, y) => x - y);

        let ans = 0;
        let i = 0;

        while (i < n) {
            let j = i;

            while (j + 1 < n && (j - i + 1 < L)) {
                let limit = a[i] + D + E * (j + 1 - i);
                if (a[j + 1] <= limit) j++;
                else break;
            }

            ans++;
            i = j + 1;
        }

        console.log(ans);
    }
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var T int
	fmt.Fscan(in, &T)

	for T > 0 {
		T--

		var n int
		var D, E int64
		var L int

		fmt.Fscan(in, &n, &D, &E, &L)

		a := make([]int64, n)
		for i := 0; i < n; i++ {
			fmt.Fscan(in, &a[i])
		}

		// 升序排序
		sort.Slice(a, func(i, j int) bool {
			return a[i] < a[j]
		})

		ans := 0
		i := 0

		for i < n {
			j := i

			for j+1 < n && (j-i+1 < L) {
				limit := a[i] + D + E*int64(j+1-i)
				if a[j+1] <= limit {
					j++
				} else {
					break
				}
			}

			ans++
			i = j + 1
		}

		fmt.Fprintln(out, ans)
	}
}
相关推荐
BothSavage9 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn10 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
烬羽11 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
先吃饱再说1 天前
判断回文字符串,从一行代码到双指针优化
算法
黄敬峰1 天前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术1 天前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六1 天前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术1 天前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试