简单负载均衡

题目描述

某工程师为了解决服务器负载过高的问题,决定使用多个服务器来分担请求消息。

现给定 k 台服务器(编号从 1 到 k),以及一批请求消息的信息,格式为到达时刻 负载大小,消息说明:

每个时刻最多只有一条消息到达;

负载大小表示服务器处理该消息所需时长。

请计算在负载分担规则下,哪些服务器处理的负载最高(服务器处理的负载为所处理的所有消息的负载累加和),并以升序返回这些服务器的编号。

负载分担规则:

按顺序循环分配服务器,如:有3台服务器且都空闲,分配的方式为 1->2->3->1... ;

如果某台服务器繁忙,则跳过该服务器;

如果一条消息到达时所有服务器繁忙,则丢弃这条消息。

解答要求

时间限制:1000ms, 内存限制:512MB

输入

第一行为服务器的个数 k,k 的范围 [1, 50000]

第二行为请求消息个数 n,n 的范围 [1, 50000]

随后的 n 行为各条消息的到达时刻和负载大小(注意并非按到达时刻升序给出)。

消息到达时刻的范围 [1, 10^9],负载大小的范围 [1, 10^9]

输出

处理负载最多的服务器编号,注意按升序输出。

样例

输入样例 1

java 复制代码
3
7
1 15
2 10
12 10
5 10
6 10
30 15
32 10

输出样例 1

java 复制代码
1 3

提示样例 1

根据输入信息,经过分析可得以下表:

到达时刻 消息负载 完成时刻(不包含) 分配服务器号
1 15 16 1
2 10 12 2
5 10 15 3
6 10 16 丢弃
12 10 22 2
30 15 45 3
32 10 42 1

根据上表分析,1和3号服务器处理的负载都为25,按照升序排列,输出的结果为:1 3

Java算法源码

java 复制代码
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Main {
    // 待实现函数,在此函数中填入答题代码
    static int[] findHighestLoadServers(int serverNum, Message[] messages) {
        boolean[] isBusy = new boolean[serverNum]; // 下标为server编号-1,值为是否忙碌
        int[] serverLoad = new int[serverNum]; // 下标为server编号-1,值为总Load
        Message[] processingMsg = new Message[serverNum]; // 下标为server编号-1,值为目前仍在处理的 message信息
        // 首先将消息按时间排序
        Arrays.sort(messages, Comparator.comparingInt(o -> o.time));
        int lastProcessIdx = -1; // 上次分配执行的服务器,从-1开始
        // 依次处理 messages
        for (Message message : messages) {
            // 首先更新时间
            updateTime(message.time, isBusy, processingMsg, serverNum);
            // 从 lastProcessIdx 下一个位置开始,循环找到第一个空闲的server
            // 按顺序循环分配服务器:i最大值可为 2 * serverNum,使用 i % serverNum 得到对应循环的下标
            for (int i = lastProcessIdx + 1; i < 2 * serverNum; i++) {
                // 不忙,说明找到空闲的Server
                if (!isBusy[i % serverNum]) {
                    processingMsg[i % serverNum] = message; // message添加到processingMsg
                    serverLoad[i % serverNum] += message.load; // 计算该server的总负载值
                    isBusy[i % serverNum] = true; // 标记该server为忙碌
                    lastProcessIdx = i % serverNum; // 记录下 lastProcessIdx 以下次循环使用
                    break;
                }
            }
        }
        // 统计结果
        List<int[]> idLoadArrList = new ArrayList<>(); // [serverId, serverLoad]
        for (int i = 0; i < serverNum; i++) {
            idLoadArrList.add(new int[] {i + 1, serverLoad[i]});
        }
        idLoadArrList.sort((o1, o2) -> o1[1] != o2[1] ? o2[1] - o1[1] : o1[0] - o2[0]); // 按serverLoad降序,serverId升序
        // 生成答案
        List<Integer> ansList = new ArrayList<>();
        ansList.add(idLoadArrList.get(0)[0]);
        int maxLoad = idLoadArrList.get(0)[1];
        int i = 1;
        // 将与最大值相等的serverId加入结果集
        while (i < idLoadArrList.size() && idLoadArrList.get(i)[1] == maxLoad) {
            ansList.add(idLoadArrList.get(i)[0]);
            i++;
        }
        return ansList.stream().mapToInt(Integer::valueOf).toArray();
    }
    
    private static void updateTime(int time, boolean[] isBusy, Message[] processingMsg, int serverNum) {
        for (int i = 0; i < serverNum; i++) {
            // 空闲的不处理
            if (!isBusy[i]) {
                continue;
            }
            // 忙碌的检查是否处理完了
            Message message = processingMsg[i];
            if (message.time + message.load <= time) {
                isBusy[i] = false;
                processingMsg[i] = null;
            }
        }
    }

    static class Message {
        int time;
        int load;
    };

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in, StandardCharsets.UTF_8.name());
        int serverNum = cin.nextInt();
        int messageNum = cin.nextInt();
        Message[] messages = new Message[messageNum];
        for (int i = 0; i < messages.length; i++) {
            Message message = new Message();
            message.time = cin.nextInt();
            message.load = cin.nextInt();
            messages[i] = message;
        }

        cin.close();

        int[] highestLoadServers = findHighestLoadServers(serverNum, messages);
        String[] strResult = Arrays.stream(highestLoadServers).mapToObj(String::valueOf).toArray(String[]::new);
        System.out.println(String.join(" ", strResult));
    }
}
相关推荐
myloveasuka4 分钟前
信号操作集函数
linux·运维·服务器·c语言·c++·vscode
亦舒.7 分钟前
宝塔面板Nginx手动配置负载均衡实战指南
运维·nginx·负载均衡
舒克起飞了2 小时前
linux系统编程——Makefile、GDB调试
linux·运维·服务器
deming_su2 小时前
轻松上手:使用Nginx实现高效负载均衡
运维·nginx·负载均衡
降世神童3 小时前
华为云Flexus+DeepSeek征文| 使用华为云CCE容器部署Dify-LLM高可用方案的验证与测试
运维·华为云·aigc
降世神童3 小时前
华为云Flexus+DeepSeek征文| 基于华为云Dify-LLM高可用平台开发运维故障处理智能体
运维·华为云·aigc
好名字更能让你们记住我5 小时前
Linux多线程(十二)之【生产者消费者模型】
linux·运维·服务器·jvm·windows·centos
门思科技5 小时前
设计可靠 LoRaWAN 设备时需要考虑的关键能力
运维·服务器·网络·嵌入式硬件·物联网
学习编程的gas5 小时前
Linux开发工具——gcc/g++
linux·运维·服务器
dessler6 小时前
Kafka-消费者(Consumer)和消费者组(Consumer Group)
linux·运维·kafka