美团研发岗 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)
	}
}
相关推荐
J2虾虾2 小时前
C 语言 sizeof 完全用法指南
c语言·数据结构·算法
阿正的梦工坊2 小时前
【Rust】03-所有权、移动与复制
开发语言·算法·rust
好评笔记3 小时前
深度学习面试八股—— GRU(Gated Recurrent Unit)
人工智能·rnn·深度学习·算法·机器学习·gru·校招
搞科研的小刘选手3 小时前
【智能计算方向专题研讨会】第三届智能计算与数据分析国际学术会议(ICDA 2026)
大数据·算法·机器学习·数据挖掘·数据分析·可视化·计算
量化君也3 小时前
桥水基金全天候策略拆解,构建中国ETF躺平版策略
大数据·人工智能·python·算法·金融·业界资讯
蓦然回首却已人去楼空3 小时前
画图专用文档
算法
洛水水3 小时前
【力扣100题】78.在排序数组中查找元素的第一个和最后一个位置
数据结构·算法·leetcode
江屿风3 小时前
C++图论基础拓扑排序算法流食般投喂
开发语言·c++·笔记·算法·排序算法
海棠AI实验室3 小时前
AI 时代文献综述:从检索到成稿的 RAG 五步法
windows·算法·自动化·llm·rag