华为校招机试 - 云服务计费(20240410)

在线OJ测试

题目详情 - 云服务计费 - HydroOJ​​​​​​​

题目描述

编写一个程序为某云服务计算客户话单,输入为某云服务的计费日志和各种计费因子的计费单价的列表,计费日志内容包含 4 个字段:

  • 时间戳
  • 客户标识
  • 计费因子
  • 计费时长

日志中如果同一客户、同一计费因子、在相同时间戳上报多次话单只能计费一次,选先上报的日志计费。

计算每个客户的话单总费用。

输入描述

第 1 行表示计费日志的条数 n

  • n 是一个正整数,范围是:1 ≤ n ≤ 1000

第 2 到 n+1 行表示云服务的计费日志,共 4 列:

  • 第 1 列表示时间戳(是一个数字字符串,长度为10) 
  • 第 2 列表示客户标识(是一个字符串,长度为1-16)
  • 第 3 列表示计费因子(是一个字符串,长度为1-16,计费因子查不到时认为计费因子单价是0)
  • 第 4 列表示计费时长(范围为0-100,当计费时长不在范围内要认为是计费日志有问题,当成计费为 0 处理)
  • 这4个字段使用逗号分隔

第 n+2 行表示计费因子的数量 m

  • m 是一个正整数,范围是:1 ≤ m ≤ 100

第 n+3 到 n+3+m 行表示各种计费因子的计费单价的列表,该表有 2 列:

  • 第1列表示计费因子 (是一个字符串,长度为1-16)
  • 第2列表示单价(是一个正整数,范围为1~100)
  • 这2个字段使用逗号分隔

输出描述

每个客户的话单总费用,共 2 列:

  • 第 1 列表示客户名
  • 第 2 列表示话单费用

2列用逗号分割,输出按客户标识字典序升序排序。

用例

输入5
1627845600,client1,factorA,10
1627845605,client2,factorB,15
1627845610,client1,factorA,5
1627845610,client1,factorB,8
1627845620,client2,factorB,20
2
factorA,5
factorB,7
输出client1,131
client2,245
说明client1 = 15 × 5 + 8 × 7 = 131
client2 = 0 × 5 + 35 × 7 = 245

题目解析

本题是一道逻辑模拟题。

主要难点在于细节把握,有如下细节

  1. 日志中如果同一客户、同一计费因子、在相同时间戳上报多次话单只能计费一次,选先上报的日志计费。
  2. 计费因子查不到时认为计费因子单价是0
  3. 计费时长(范围为0-100,当计费时长不在范围内要认为是计费日志有问题,当成计费为 0 处理)
  4. 输出按客户标识字典序升序排序

对于1,其实就是让我们去除客户的重复日志信息,而日志是否重复的判断标准是:

同一客户、同一计费因子、相同时间戳

因此根据第 2 到 n+1 行输入的日志信息,一旦后面的日志和前面的日志上面三要素相同,则后面的日志就是重复的,可以忽略。

具体去重实现,针对不同语言有不同办法,大家可以看下面源码的具体实现。


对于2,即某个客户名下某个日志的计费因子不存在(即不存在于第 n+3 到 n+3+m 行),那么此时计费因子单价为0,即对应日志不产生费用。


对于3,需要我们日志的计算时长进行范围判断,如果不在指定范围,则对应日志不产生费用。


对于4,输出按客户标识字典序升序排序

JS算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;void (async function () {// 计费日志的条数const n = parseInt(await readline());// key是客户id,val是客户的计费日志容器const logs = {};for (let i = 0; i < n; i++) {// 时间戳,客户标识,计费因子,计费时长const [timestamp, custId, factor, duration] = (await readline()).split(",");// 初始化客户的日志容器(对象作为容器)if (logs[custId] == undefined) {logs[custId] = {};}const key = timestamp + factor;// 若日志的客户标识、时间戳、计费因子三要素相同,则认为日志重复,不加入重复日志if (logs[custId][key] != undefined) {continue;}// 日志不重复,则记录日志信息[计费因子,计费时长]logs[custId][key] = [factor, parseInt(duration)];}// 计费因子的数量const m = parseInt(await readline());// key是计费因子,val是计费因子单价const unit_price = {};for (let j = 0; j < m; j++) {// 计费因子,单价const [factor, price] = (await readline()).split(",");unit_price[factor] = parseInt(price);}// 客户花费,key是客户id,val是客户所有log的花费之和const fees = {};for (let custId in logs) {for (let key in logs[custId]) {let [factor, duration] = logs[custId][key];// 计费时长(范围为0-100), 当计费时长不在范围内要认为是计费日志有问题,当成计费为 0 处理if (duration > 100 || duration < 0) {duration = 0;}// 计费因子查不到时认为计费因子单价是0const price = unit_price[factor] ?? 0;fees[custId] = (fees[custId] ?? 0) + duration * price;}}// 结果按照客户标识(fees的key)进行升序Object.keys(fees).sort().forEach((custId) => {console.log(`${custId},${fees[custId]}`);});
})();

Java算法源码

import java.util.*;public class Main {static class Log {String custId;String timestamp;String factor;int duration;@Overridepublic int hashCode() {// 日志中如果同一客户、同一计费因子、在相同时间戳上报多次话单只能计费一次,选先上报的日志计费// 因此若日志的客户表示、时间戳、计费因子三要素相同,则认为日志重复return custId.hashCode() + timestamp.hashCode() + factor.hashCode();}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (obj == null || getClass() != obj.getClass()) {return false;}Log log = (Log) obj;// 日志中如果同一客户、同一计费因子、在相同时间戳上报多次话单只能计费一次,选先上报的日志计费// 因此若日志的客户表示、时间戳、计费因子三要素相同,则认为日志重复return custId.equals(log.custId) && timestamp.equals(log.timestamp) && factor.equals(log.factor);}}public static void main(String[] args) {// 设置逗号和换行符作为读取分隔符Scanner sc = new Scanner(System.in).useDelimiter("[,\n]");// 计费日志的条数int n = sc.nextInt();// key是客户id,val是客户的计费日志HashMap<String, HashSet<Log>> logs = new HashMap<>();for (int i = 0; i < n; i++) {Log log = new Log();// 时间戳log.timestamp = sc.next();// 客户标识log.custId = sc.next();// 计费因子log.factor = sc.next();// 计费时长log.duration = sc.nextInt();logs.putIfAbsent(log.custId, new HashSet<>());logs.get(log.custId).add(log);}// 计费因子的数量int m = sc.nextInt();// key是计费因子,val是计费因子单价HashMap<String, Integer> unit_price = new HashMap<>();for (int i = 0; i < m; i++) {// 计费因子String factor = sc.next();// 单价int price = sc.nextInt();unit_price.put(factor, price);}// 客户花费,key是客户id,val是客户所有log的花费之和TreeMap<String, Integer> fees = new TreeMap<>(); // TreeMap会根据key的自然顺序进行排序,这里的key是custId字符串,自然顺序就是字典序升序for (String custId : logs.keySet()) {for (Log log : logs.get(custId)) {// 计费时长(范围为0-100), 当计费时长不在范围内要认为是计费日志有问题,当成计费为 0 处理if (log.duration > 100 || log.duration < 0) {log.duration = 0;}// 计费因子查不到时认为计费因子单价是0int price = unit_price.getOrDefault(log.factor, 0);fees.put(custId, fees.getOrDefault(custId, 0) + log.duration * price);}}for (String custId : fees.keySet()) {System.out.println(custId + "," + fees.get(custId));}}
}

Python算法源码

# 算法入口
def solution():# 计费日志的条数n = int(input())# key是客户id,val是客户的计费日志容器logs = {}for _ in range(n):# 时间戳,客户标识,计费因子,计费时长timestamp, custId, factor, duration = input().split(",")# 初始化客户的日志容器(对象作为容器)if custId not in logs:logs[custId] = {}key = timestamp + factor# 若日志的客户标识、时间戳、计费因子三要素相同,则认为日志重复,不加入重复日志if key in logs[custId]:continue# 日志不重复,则记录日志信息[计费因子,计费时长]logs[custId][key] = (factor, int(duration))# 计费因子的数量m = int(input())# key是计费因子,val是计费因子单价unit_price = {}for _ in range(m):# 计费因子,单价factor, price = input().split(",")unit_price[factor] = int(price)# 客户花费,key是客户id,val是客户所有log的花费之和fees = {}for custId in logs:for factor, duration in logs[custId].values():# 计费时长(范围为0-100), 当计费时长不在范围内要认为是计费日志有问题,当成计费为 0 处理if duration > 100 or duration < 0:duration = 0# 计费因子查不到时认为计费因子单价是0price = unit_price.get(factor, 0)fees[custId] = fees.get(custId, 0) + price * duration# 结果按照客户标识(fees的key)进行升序for custId in sorted(fees.keys()):print(f"{custId},{fees[custId]}")# 算法调用
solution()

C算法源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_N 1000
#define MAX_SIZE 20typedef struct {char *timestamp;char *custId;char *factor;int duration;
} Log;Log *new_Log() {Log *log = (Log *) malloc(sizeof(Log));log->timestamp = (char *) calloc(MAX_SIZE, sizeof(char));log->custId = (char *) calloc(MAX_SIZE, sizeof(char));log->factor = (char *) calloc(MAX_SIZE, sizeof(char));log->duration = 0;return log;
}typedef struct {char *custId;Log **logs;int logs_size;int fee;
} Customer;Customer *new_Customer(char *custId) {Customer *customer = (Customer *) malloc(sizeof(Customer));customer->custId = (char *) calloc(MAX_SIZE, sizeof(char));strcpy(customer->custId, custId);customer->logs = (Log **) calloc(MAX_N, sizeof(Log *));customer->logs_size = 0;customer->fee = 0;return customer;
}void add_Log(Customer *customer, Log *log) {for (int i = 0; i < customer->logs_size; i++) {char *custId = customer->logs[i]->custId;char *timestamp = customer->logs[i]->timestamp;char *factor = customer->logs[i]->factor;// 日志中如果同一客户、同一计费因子、在相同时间戳上报多次话单只能计费一次,选先上报的日志计费// 因此若日志的客户表示、时间戳、计费因子三要素相同,则认为日志重复if (strcmp(custId, log->custId) == 0 && strcmp(timestamp, log->timestamp) == 0 &&strcmp(factor, log->factor) == 0) {// 重复日志不加入return;}}// 不重复日志加入customer->logs[customer->logs_size++] = log;
}int cmp(const void *a, const void *b) {Customer *A = *((Customer **) a);Customer *B = *((Customer **) b);return strcmp(A->custId, B->custId);
}int main() {// 计费日志的条数int n;scanf("%d", &n);// 收集客户对象Customer *customers[MAX_N] = {NULL};int customers_size = 0;for (int i = 0; i < n; i++) {getchar();// 日志对象Log *log = new_Log();scanf("%[^,],%[^,],%[^,],%d", log->timestamp, log->custId, log->factor, &log->duration);// 检查该日志对应的客户是否已记录到customers数组int j = 0;for (; j < customers_size; j++) {if (strcmp(customers[j]->custId, log->custId) == 0) {break;}}// 如果未记录过该客户,则新建该客户对象if (j == customers_size) {customers[customers_size++] = new_Customer(log->custId);}// 加入该日志到该客户对象中add_Log(customers[j], log);}// 计费因子的数量int m;scanf("%d", &m);for (int i = 0; i < m; i++) {getchar();// 计费因子char factor[MAX_SIZE];// 单价int price;scanf("%[^,],%d", factor, &price);// 遍历客户对象for (int j = 0; j < customers_size; j++) {Customer *customer = customers[j];// 遍历客户对象下的日志集合for (int k = 0; k < customer->logs_size; k++) {Log *log = customer->logs[k];// 如果该日志的计费因子和当前计费因子相同,则计算当前日志的花费,并求和到客户总费用fee中// 注意:// 1、计费时长(范围为0-100), 当计费时长不在范围内要认为是计费日志有问题,当成计费为 0 处理// 2、计费因子查不到时认为计费因子单价是0if (log->duration >= 0 && log->duration <= 100 && strcmp(log->factor, factor) == 0) {customer->fee += log->duration * price;}}}}// 结果按照客户标识进行升序qsort(customers, customers_size, sizeof(customers[0]), cmp);for (int i = 0; i < customers_size; i++) {printf("%s,%d\n", customers[i]->custId, customers[i]->fee);}return 0;
}

C++算法源码

#include <bits/stdc++.h>
using namespace std;vector<string> splitCin(char delimiter) {string s;cin >> s;stringstream ss(s);string token;vector<string> res;while (getline(ss, token, delimiter)) {res.emplace_back(token);}return res;
}int main() {// 计费日志的条数int n;cin >> n;// key是客户id,val是客户的计费日志map<string, map<string, vector<string>>> logs;for (int i = 0; i < n; i++) {vector<string> tmp = splitCin(',');// 时间戳string timestamp = tmp[0];// 客户标识string custId = tmp[1];// 计费因子string factor = tmp[2];// 计费时长string duration = tmp[3];if (logs.count(custId) == 0) {logs[custId] = map<string, vector<string>>();}// 若日志的客户标识、时间戳、计费因子三要素相同,则认为日志重复,不加入重复日志string key = timestamp + factor;if (logs[custId].count(key) > 0) {continue;}// 日志不重复,则记录日志信息[计费因子,计费时长]logs[custId][key] = vector<string>{factor, duration};}// 计费因子的数量int m;cin >> m;// key是计费因子,val是计费因子单价map<string, int> unit_price;for (int i = 0; i < m; i++) {vector<string> tmp = splitCin(',');// 计费因子string factor = tmp[0];// 单价string price = tmp[1];unit_price[factor] = stoi(price);}// 客户花费,key是客户id,val是客户所有log的花费之和map<string, int> fees;for (const auto &pair: logs) {string custId = pair.first;for (const auto &item: logs[custId]) {vector<string> log = item.second;string factor = log[0];int duration = stoi(log[1]);// 计费时长(范围为0-100), 当计费时长不在范围内要认为是计费日志有问题,当成计费为 0 处理if (duration > 100 || duration < 0) {duration = 0;}// 计费因子查不到时认为计费因子单价是0int price = unit_price[factor];fees[custId] += duration * price;}}// 结果按照客户标识(fees的key)进行升序, map自动按照key升序for (const auto &pair: fees) {cout << pair.first << "," << pair.second << endl;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/816108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux mkisofs命令教程:创建和编辑ISO文件(附实例详解和注意事项)

Linux mkisofs命令介绍 mkisofs是一个用于创建ISO 9660映像文件的实用程序。它可以从磁盘上的文件生成ISO 9660/JOLIET/HFS混合文件系统。这个文件系统能够生成Rock Ridge交换协议所规定的系统使用共享协议记录&#xff08;SUSP&#xff09;。这些记录用于在ISO 9660文件系统中…

C++ UML 类图介绍与设计

1 类图概述 UML(Unified Modeling Language)&#xff0c;即统一建模语言&#xff0c;是用来设计软件的可视化建模语言。它的特点是简单、统一、图形化、能表达软件设计中的动态与静态信息。UML从目标系统的不同角度出发&#xff0c;定义了用例图、类图、对象图、状态图、活动图…

深拷贝总结

JSON.parse(JSON.stringify(obj)) 这行代码的运行过程&#xff0c;就是利用 JSON.stringify 将js对象序列化&#xff08;JSON字符串&#xff09;&#xff0c;再使用JSON.parse来反序列化&#xff08;还原&#xff09;js对象&#xff1b;序列化的作用是存储和传输。&#xff08…

命令行操作

1、pwd(显示当前工作所在的目录) pwd 命令,是 Print Working Directory (打印工作目录)的缩写,功能是显示用户当前所处的工作目录。 2、ls(列出当前目录中包含的所有文件和子目录) ls 命令,list 的缩写,是最常见的目录操作命令,其主要功能是显示当前目录下的内容…

高级IO——React服务器简单实现

3.4Reactor服务器实现 1.connect封装 ​ 每一个连接都要有一个文件描述符和输入输出缓冲区&#xff0c;还有读、写、异常处理的回调方法&#xff1b; ​ 还包括指向服务器的回指指针&#xff1b; class connection; class tcpserver;using func_t std::function<void(s…

亚马逊云科技官方重磅发布GenAI应用开发学习路线(全免费)

今天小李哥给大家分享的是亚马逊云科技&#xff08;AWS&#xff09;最近官方发布的GenAI应用开发最佳学习路线&#xff0c;不仅内容非常全面更主要的是全部免费&#xff01;大家动动小手就能成为GenAI开发大&#x1f42e;&#xff01; 1️⃣这个GenAI开发学习路线包括什么&…

https://ac.nowcoder.com/acm/contest/78309

A-scx 的散文诗句_华中农业大学第十三届程序设计竞赛&#xff08;同步赛&#xff09; (nowcoder.com) #include<bits/stdc.h> using namespace std; #define int long long const int N3e56; const int inf0x3f3f3f3f; int a[N]; void solve() {int n;cin>>n;int …

遥感卫星:探索地球的科技之旅

遥感卫星是人类探索地球、理解地球、保护地球的重要工具&#xff0c;其发展历程承载了人类对地球的探索与认知的历程。从最初的概念到如今的高科技应用&#xff0c;遥感卫星技术的发展见证了人类科技的不断进步与创新。 初心萌芽&#xff1a; 遥感卫星的发展始于20世纪中叶&…

【计算机网络】(一)计算机网络概述

文章目录 【计算机网络】&#xff08;一&#xff09;计算机网络概述前言1.1 计算机网络在信息时代中的作用1.2 互联网概述1.2.1 网络的网络1.2.2 互联网基础结构发展的三个阶段1.2.3 互联网标准化工作 1.3 互联网的组成1.3.1 互联网的边缘部分1.3.2 互联网的核心部分 1.4 计算机…

C语言高质量编程之assert()和const

目录 编程中常见的错误 assert() const 编程中常见的错误 在编程中我们通常会遇到三种错误形式&#xff0c;分别是&#xff1a;编译型错误&#xff0c;链接型错误&#xff0c;运行时错误。 编译型错误&#xff1a; 在编译阶段发生的错误&#xff0c;绝大多数情况是由语法错误…

类 继承 (均未写完)

一、Fraction类&#xff08;分数&#xff09; class Fraction:def __init__(self, top, bottom):if bottom 0:print("Error:分子分母不能为0")else:n gcd(top, bottom)self.num top // nself.den bottom // n# 分数的输出def __str__(self):return str(self.num)…

Iterator接口用法详解(Java)

Iterator接口 Iterator 接口是 Java 集合框架中的一个核心接口&#xff0c;用于遍历集合中的元素。它定义了一种迭代器的行为&#xff0c;允许按顺序访问集合中的元素&#xff0c;而不需要暴露集合内部的结构。 当你使用 Iterator 接口遍历集合时&#xff0c;你实际上在使用设…

进阶级Python编程题(5)洛谷(不高兴的津津)和index函数的用法

题目描述 津津上初中了。妈妈认为津津应该更加用功学习&#xff0c;所以津津除了上学之外&#xff0c;还要参加妈妈为她报名的各科复习班。另外每周妈妈还会送她去学习朗诵、舞蹈和钢琴。但是津津如果一天上课超过八个小时就会不高兴&#xff0c;而且上得越久就会越不高兴。假…

利用Sentinel解决雪崩问题(二)隔离和降级

前言&#xff1a; 虽然限流可以尽量避免因高并发而引起的服务故障&#xff0c;但服务还会因为其它原因而故障。而要将这些故障控制在一定范围避免雪崩&#xff0c;就要靠线程隔离(舱壁模式)和熔断降级手段了&#xff0c;不管是线程隔离还是熔断降级&#xff0c;都是对客户端(调…

vue源码解析——v-if和v-for哪个优先级高,如何避免两者同时使用

首先&#xff0c;官方不推荐v-if和v-for在同一个元素上使用。其次&#xff0c;如果两者同时使用&#xff0c;v-if和v-for的优先级怎么确定&#xff1f;在vue2和vue3中这两者的优先级顺序不一样。vue2是v-for优先&#xff0c;条件不存在时也会渲染多个注释节点。在vue3中进行了改…

基于51单片机的无线病床呼叫系统设计—LCD1602显示

基于51单片机的无线病床呼叫系统 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.病人按下按键&#xff0c;LCD1602显示对应的床位号&#xff1b; 2.多人同时呼叫&#xff0c;显示屏同时显示&#xf…

文献阅读:Viv:在 web 上多尺度可视化高分辨率多重生物成像数据

文献介绍 「文献题目」 Viv: multiscale visualization of high-resolution multiplexed bioimaging data on the web 「研究团队」 Nils Gehlenborg&#xff08;美国哈佛医学院&#xff09; 「发表时间」 2022-05-11 「发表期刊」 Nature Methods 「影响因子」 47.9 「DOI…

第17天:信息打点-语言框架开发组件FastJsonShiroLog4jSpringBoot等

第十七天 本课意义 1.CMS识别到后期漏洞利用和代码审计 2.开发框架识别到后期漏洞利用和代码审计 3.开发组件识别到后期漏洞利用和代码审计 一、CMS指纹识别-不出网程序识别 1.概念 CMS指纹识别一般能识别到的都是以PHP语言开发的网页为主&#xff0c;其他语言开发的网页识…

Unix环境高级编程-学习-09-多线程之读写锁与条件变量(包含线程池的部分实现与测试验证)

目录 一、多线程相关文章链接 二、自由抒发 1、读写锁 2、条件变量 三、函数介绍 1、pthread_rwlock_init &#xff08;1&#xff09;声明 &#xff08;2&#xff09;作用 &#xff08;3&#xff09;参数 &#xff08;4&#xff09;返回值 &#xff08;5&#xff09;…

深度学习学习日记4.14 数据增强 Unet网络部分

数据增强 transforms.Compose([&#xff1a;这表示创建一个转换组合&#xff0c;将多个数据转换操作串联在一起 transforms.RandomHorizontalFlip()&#xff1a;这个操作是随机水平翻转图像&#xff0c;以增加数据的多样性。它以一定的概率随机地水平翻转输入的图像。 transfo…