【双机位A卷】华为OD笔试之【哈希表】双机位A-采购订单【Py/Java/C++/C/JS/Go六种语言】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
可上 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳od1441了解算法冲刺训练(备注【CSDN】否则不通过)
文章目录
- 相关推荐阅读
- 题目描述与示例
- 题目描述
- 输入描述
- 输出描述
- 补充说明
- 示例一
- 输入
- 输出
- 说明
- 示例二
- 输入
- 输出
- 说明
- 示例三
- 输入
- 输出
- 说明
- 解题思路
- 代码
- Python
- Java
- C++
- C
- Node JavaScript
- Go
- 时空复杂度
- 华为OD算法/大厂面试高频题算法练习冲刺训练
相关推荐阅读
- 【华为OD机考正在更新】2025年双机位A卷真题【完全原创题解 | 详细考点分类 | 不断更新题目 | 六种主流语言Py+Java+Cpp+C+Js+Go】
- 【华为OD机考】2025C+2025B+2024E+D卷真题【完全原创题解 | 详细考点分类 | 不断更新题目】
- 【华为OD笔试】双机位A+2025C+2025B+2024E+D卷真题机考套题汇总【真实反馈,不断更新,限时免费】
- 【华为OD笔试】2024E+D卷命题规律解读【分析500+场OD笔试考点总结】
- 【华为OD流程】性格测试选项+注意事项】
题目练习网址:【哈希表】双机位A-采购订单
题目描述与示例
题目描述
在一个采购系统中,采购申请(PR)需要经过审批后才能生成采购订单(PO)。每个PR包含商品的单价(假设相同商品的单价一定是一样的)及数量信息。
系统要求对商品进行分类处理:单价高于100元的商品需要单独处理,单价低于或等于100元的相同商品可以合并到同一采购订单PO中。针对单价低于100的小额订单,如果量大可以打折购买。
具体规则如下:
如果PR状态为"审批通过",则将其商品加入到PO中。如果PR的状态为"审批拒绝"或"待审批",则忽略该PR。
对于单价高于100元的商品,每个商品单独生成一条PO记录。对于单价低于或等于100元的商品,将相同商品的数量合并到一条PO记录中。
如果商品单价<100且商品数量>=100,则单价打9折。
输入描述
第一行包含整数N,表示PR的数量。
接下来N行,每行包含四个用空格分割的整数,按顺序表示:商品ID,数量,单价,PR状态 (0表示审批通过,1表示审批拒绝,2表示待审批)
输出描述
输出若干行,每行表示一条PO记录,按以下格式输出:
对于单价高于100元的商品:商品ID 数量 单价
对于单价低于或等于100元的商品: 商品ID 总数量 打折后的单价(向上取整)
输出的PO记录按商品ID升序升序排列,相同商品按照数量降序排列
补充说明
2 <= n <= 10001 <= 商品价格 <= 2001 <= 商品数量 <= 10001 <= 商品编号 <= 1000
示例一
输入
2
1 200 90 0
2 30 101 0
输出
1 200 81
2 30 101
说明
商品1的原始单价为90,审批通过,生成一条PO,满足打折条件,打折后单价为81。
商品2的单价为101,审批通过,生成一条PO
示例二
输入
3
1 10 90 0
1 5 90 0
2 8 120 0
输出
1 15 90
2 8 120
说明
PR1和PR2均为商品1,单价90,审批通过,单价低于100元,合并数量为15
PR3为商品2,单价120元,审批通过,单价高于100元,单独生成一条PO记录。
示例三
输入
4
1 5 80 0
2 3 120 0
3 2 90 1
4 10 150 2
输出
1 5 80
2 3 120
说明
PR1:商品1,单价80元,审批通过,单价低于100元,合并到PO中。
PR2:商品2,单价120元,审批通过,单价高于100元,单独生成一条PO记录。
PR3:审批拒绝, 忽略。
PR4:待审批,忽略。
解题思路
题目的细节较多,需要仔细读题。注意以下几个点
- 审批状态必须为
0,如果审批状态为1或2,则直接忽略该条订单 - 单价 > 100,不合并订单,不打折
- 单价 = 100,合并订单,不打折
- 单价 < 100,合并订单,打折
单价 = 100的情况,属于特殊的边界情况,在题目中需要仔细读题才能判断出来。
当单价 ≤ 100时,本题涉及到多个同类型商品订单的合并过程。
容易想到用哈希表来维护这个过程。
我们可以设计一个哈希表dic,其中key为商品编号,由于需要同时储存商品单价和商品数量,value可以设计为一个长度为2的数组来储存上述信息。
而不需要合并的订单,我们可以直接用另一个列表lst来储存,同时储存编号,单价,数量。
故可用如下代码来完成数组的更新和哈希表的构建
# 储存有效订单的列表
lst = list()
# 储存单价小于等于100的商品信息的哈希表
dic = dict()# 循环n次
for _ in range(n):# 输入订单信息,包含编号、数量、单价、状态idx, num, price, state = map(int, input().split())# 如果状态为1或2,则属于无效订单,直接跳过if state != 0:continue# 如果单价大于100,则需要单独储存# 将其编号、数量、单价作为一个三元组存入lst中# 储存后跳过后续判断if price > 100:lst.append([idx, num, price])continue# 如果单价小于等于100# 判断其是否位于哈希表中# 如果是首次出现,则以编号为key# 数量和单价构成的二元组作为value# 构建键值对if idx not in dic:dic[idx] = [num, price]# 如果当前商品已经存在于哈希表中# 则将数量累加到哈希表中else:dic[idx][0] += num
哈希表构建完毕之后,我们需要再次遍历整个哈希表,将其中可以打折的商品进行单价的修改。
# 再次遍历哈希表中的所有键值对
for idx in dic:num, price = dic[idx]# 如果数量大于等于100且单价小于100# 则单价打9折,向上取整if num >= 100 and price < 100:dic[idx][1] = ceil(price * 0.9)
接下来我们需要将哈希表dic中的键值对,同样根据编号,数量,单价的格式合并到lst中。
# 再次遍历哈希表中的所有键值对
# 将更新后的商品信息,按照编号、数量、单价的三元组格式
# 存入lst中
for idx in dic:num, price = dic[idx]lst.append([idx, num, price])
最后将lst中的元素进行排序,按照先编号升序排序,后根据数量降序排序的规则进行排序。即
# 对lst中的元素进行排序
# 先按照编号升序排序,在按照数量降序排序
lst.sort(key = lambda x: (x[0], -x[1]))
代码
Python
# 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
# 地址:https://www.odalgo.com
# 华为OD机试刷题网站:https://www.algomooc.com
# 添加微信 278166530 获取华为 OD 笔试真题题库和视频# 题目:【哈希表】双机位A-采购订单
# 分值:100
# 作者:许老师-闭着眼睛学数理化
# 算法:哈希表/排序
# 代码看不懂的地方,请直接在群上提问from math import ceil# 输入订单条数
n = int(input())# 储存有效订单的列表
lst = list()
# 储存单价小于等于100的商品信息的哈希表
dic = dict()# 循环n次
for _ in range(n):# 输入订单信息,包含编号、数量、单价、状态idx, num, price, state = map(int, input().split())# 如果状态为1或2,则属于无效订单,直接跳过if state != 0:continue# 如果单价大于100,则需要单独储存# 将其编号、数量、单价作为一个三元组存入lst中# 储存后跳过后续判断if price > 100:lst.append([idx, num, price])continue# 如果单价小于等于100# 判断其是否位于哈希表中# 如果是首次出现,则以编号为key# 数量和单价构成的二元组作为value# 构建键值对if idx not in dic:dic[idx] = [num, price]# 如果当前商品已经存在于哈希表中# 则将数量累加到哈希表中else:dic[idx][0] += num# 再次遍历哈希表中的所有键值对
for idx in dic:num, price = dic[idx]# 如果数量大于等于100且单价小于100# 则单价打9折,向上取整if num >= 100 and price < 100:dic[idx][1] = ceil(price * 0.9)# 再次遍历哈希表中的所有键值对
# 将更新后的商品信息,按照编号、数量、单价的三元组格式
# 存入lst中
for idx in dic:num, price = dic[idx]lst.append([idx, num, price])# 对lst中的元素进行排序
# 先按照编号升序排序,在按照数量降序排序
lst.sort(key = lambda x: (x[0], -x[1]))# 输出答案
for idx, num, price in lst:print(idx, num, price)
Java
// 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
// 地址:https://www.odalgo.com
// 华为OD机试刷题网站:https://www.algomooc.com
// 添加微信 278166530 获取华为 OD 笔试真题题库和视频// 题目:【哈希表】双机位A-采购订单
// 分值:100
// 作者:许老师-闭着眼睛学数理化
// 算法:哈希表/排序
// 代码看不懂的地方,请直接在群上提问import java.util.*;
import java.io.*;public class Main {public static void main(String[] args) throws IOException {Scanner sc = new Scanner(System.in);// 输入订单条数int n = sc.nextInt();// 储存有效订单的列表List<int[]> lst = new ArrayList<>();// 储存单价小于等于100的商品信息的哈希表Map<Integer, int[]> dic = new HashMap<>();// 循环n次for (int i = 0; i < n; i++) {// 输入订单信息,包含编号、数量、单价、状态int idx = sc.nextInt();int num = sc.nextInt();int price = sc.nextInt();int state = sc.nextInt();// 如果状态为1或2,则属于无效订单,直接跳过if (state != 0) {continue;}// 如果单价大于100,则需要单独储存// 将其编号、数量、单价作为一个三元组存入lst中if (price > 100) {lst.add(new int[] {idx, num, price});continue;}// 如果单价小于等于100// 判断其是否位于哈希表中if (!dic.containsKey(idx)) {dic.put(idx, new int[] {num, price});} else {// 如果已存在,则数量累加dic.get(idx)[0] += num;}}// 遍历哈希表中的所有键值对for (Map.Entry<Integer, int[]> entry : dic.entrySet()) {int idx = entry.getKey();int num = entry.getValue()[0];int price = entry.getValue()[1];// 如果数量大于等于100且单价小于100,则单价打9折,向上取整if (num >= 100 && price < 100) {entry.getValue()[1] = (int) Math.ceil(price * 0.9);}}// 将更新后的哈希表内容转为三元组形式加入lst中for (Map.Entry<Integer, int[]> entry : dic.entrySet()) {int idx = entry.getKey();int num = entry.getValue()[0];int price = entry.getValue()[1];lst.add(new int[] {idx, num, price});}// 对lst进行排序,先按照编号升序,再按照数量降序lst.sort((a, b) -> {if (a[0] != b[0]) {return a[0] - b[0];}return b[1] - a[1]; // 数量降序});// 输出答案for (int[] item : lst) {System.out.println(item[0] + " " + item[1] + " " + item[2]);}}
}
C++
// 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
// 地址:https://www.odalgo.com
// 华为OD机试刷题网站:https://www.algomooc.com
// 添加微信 278166530 获取华为 OD 笔试真题题库和视频// 题目:【哈希表】双机位A-采购订单
// 分值:100
// 作者:许老师-闭着眼睛学数理化
// 算法:哈希表/排序
// 代码看不懂的地方,请直接在群上提问#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <cmath>
using namespace std;int main() {int n;// 输入订单条数cin >> n;// 储存有效订单的列表(三元组:idx, num, price)vector<vector<int>> lst;// 储存单价 <= 100 的商品信息的哈希表unordered_map<int, pair<int, int>> dic;// 循环n次for (int i = 0; i < n; i++) {int idx, num, price, state;cin >> idx >> num >> price >> state;// 如果状态为1或2,则属于无效订单,直接跳过if (state != 0) continue;// 如果单价 > 100,直接入列表,不合并if (price > 100) {lst.push_back({idx, num, price});continue;}// 如果单价 <= 100,合并相同编号订单(只累加数量,保留首次价格)if (dic.find(idx) == dic.end()) {dic[idx] = {num, price};} else {dic[idx].first += num; // 数量累加}}// 遍历哈希表,处理折扣for (auto &p : dic) {int &num = p.second.first;int &price = p.second.second;// 数量>=100 且 单价<100,打9折,向上取整if (num >= 100 && price < 100) {price = ceil(price * 0.9);}}// 将dic内容写回lstfor (auto &p : dic) {int idx = p.first;int num = p.second.first;int price = p.second.second;lst.push_back({idx, num, price});}// 排序:编号升序,数量降序sort(lst.begin(), lst.end(), [](const vector<int> &a, const vector<int> &b) {if (a[0] != b[0]) return a[0] < b[0];return a[1] > b[1];});// 输出答案for (auto &item : lst) {cout << item[0] << " " << item[1] << " " << item[2] << endl;}return 0;
}
C
// 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
// 地址:https://www.odalgo.com
// 华为OD机试刷题网站:https://www.algomooc.com
// 添加微信 278166530 获取华为 OD 笔试真题题库和视频// 题目:【哈希表】双机位A-采购订单
// 分值:100
// 作者:许老师-闭着眼睛学数理化
// 算法:哈希表/排序
// 代码看不懂的地方,请直接在群上提问#include <stdio.h>
#include <stdlib.h>
#include <math.h>#define MAX_ORDERS 10000 // 最大订单数// 定义结构体用于存储订单信息(编号,数量,单价)
typedef struct {int idx;int num;int price;
} Order;// 定义哈希表节点
typedef struct HashNode {int idx;int num;int price;struct HashNode *next;
} HashNode;#define HASH_SIZE 20011 // 哈希表大小(素数)// 哈希函数(取模)
int hash(int key) {return key % HASH_SIZE;
}// 在哈希表中查找订单编号对应节点
HashNode* find(HashNode* table[], int idx) {int h = hash(idx);HashNode *cur = table[h];while (cur) {if (cur->idx == idx) return cur;cur = cur->next;}return NULL;
}// 插入或更新哈希表节点
void insert_or_update(HashNode* table[], int idx, int num, int price) {int h = hash(idx);HashNode *node = find(table, idx);if (node) {node->num += num; // 如果存在,则数量累加} else {// 否则新建节点插入链表头node = (HashNode*)malloc(sizeof(HashNode));node->idx = idx;node->num = num;node->price = price;node->next = table[h];table[h] = node;}
}int compare(const void *a, const void *b) {Order *x = (Order*)a;Order *y = (Order*)b;if (x->idx != y->idx) return x->idx - y->idx; // 按编号升序return y->num - x->num; // 数量降序
}int main() {int n;// 输入订单条数scanf("%d", &n);Order lst[MAX_ORDERS]; // 存储有效订单(三元组)int lst_size = 0;// 初始化哈希表HashNode* dic[HASH_SIZE] = {0};// 循环n次读取订单for (int i = 0; i < n; i++) {int idx, num, price, state;scanf("%d %d %d %d", &idx, &num, &price, &state);// 如果状态为1或2,则属于无效订单,直接跳过if (state != 0) continue;// 如果单价 > 100 直接入数组,不合并if (price > 100) {lst[lst_size++] = (Order){idx, num, price};continue;}// 否则加入哈希表中累加数量insert_or_update(dic, idx, num, price);}// 遍历哈希表,处理折扣for (int i = 0; i < HASH_SIZE; i++) {HashNode *cur = dic[i];while (cur) {if (cur->num >= 100 && cur->price < 100) {cur->price = (int)ceil(cur->price * 0.9); // 单价打9折,向上取整}cur = cur->next;}}// 将哈希表内容写回数组for (int i = 0; i < HASH_SIZE; i++) {HashNode *cur = dic[i];while (cur) {lst[lst_size++] = (Order){cur->idx, cur->num, cur->price};cur = cur->next;}}// 排序:编号升序,数量降序qsort(lst, lst_size, sizeof(Order), compare);// 输出结果for (int i = 0; i < lst_size; i++) {printf("%d %d %d\n", lst[i].idx, lst[i].num, lst[i].price);}return 0;
}
Node JavaScript
// 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
// 地址:https://www.odalgo.com
// 华为OD机试刷题网站:https://www.algomooc.com
// 添加微信 278166530 获取华为 OD 笔试真题题库和视频// 题目:【哈希表】双机位A-采购订单
// 分值:100
// 作者:许老师-闭着眼睛学数理化
// 算法:哈希表/排序
// 代码看不懂的地方,请直接在群上提问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 index = 0;// 输入订单条数const n = parseInt(input[index++]);// 储存有效订单的列表const lst = [];// 储存单价小于等于100的商品信息的哈希表const dic = new Map();// 循环n次读取订单信息for (let i = 0; i < n; i++) {const [idx, num, price, state] = input[index++].split(' ').map(Number);// 如果状态为1或2,则属于无效订单,直接跳过if (state !== 0) {continue;}// 如果单价大于100,单独存入lstif (price > 100) {lst.push([idx, num, price]);continue;}// 单价小于等于100的商品处理逻辑if (!dic.has(idx)) {dic.set(idx, [num, price]);} else {dic.get(idx)[0] += num; // 累加数量}}// 遍历哈希表,处理满足折扣条件的商品dic.forEach((value, idx) => {const [num, price] = value;if (num >= 100 && price < 100) {dic.set(idx, [num, Math.ceil(price * 0.9)]);}});// 将哈希表中的订单加入lst列表dic.forEach((value, idx) => {const [num, price] = value;lst.push([idx, num, price]);});// 对lst进行排序:先编号升序,再数量降序lst.sort((a, b) => a[0] !== b[0] ? a[0] - b[0] : b[1] - a[1]);// 输出答案lst.forEach(item => {console.log(item.join(' '));});
});
Go
// 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
// 地址:https://www.odalgo.com
// 华为OD机试刷题网站:https://www.algomooc.com
// 添加微信 278166530 获取华为 OD 笔试真题题库和视频// 题目:【哈希表】双机位A-采购订单
// 分值:100
// 作者:许老师-闭着眼睛学数理化
// 算法:哈希表/排序
// 代码看不懂的地方,请直接在群上提问package mainimport ("bufio""fmt""math""os""sort"
)func main() {reader := bufio.NewReader(os.Stdin)var n int// 输入订单条数fmt.Fscan(reader, &n)// 储存有效订单的列表lst := make([][]int, 0)// 储存单价小于等于100的商品信息的哈希表(key=编号, value=[数量, 单价])dic := make(map[int][]int)// 循环读取订单for i := 0; i < n; i++ {var idx, num, price, state intfmt.Fscan(reader, &idx, &num, &price, &state)// 如果状态为1或2,则属于无效订单if state != 0 {continue}// 单价大于100,则加入lstif price > 100 {lst = append(lst, []int{idx, num, price})continue}// 单价小于等于100:处理哈希表if _, exists := dic[idx]; !exists {dic[idx] = []int{num, price}} else {dic[idx][0] += num // 累加数量}}// 遍历哈希表中的订单,处理折扣for idx, data := range dic {num, price := data[0], data[1]// 数量大于等于100 且 单价小于100 的订单,单价打9折(向上取整)if num >= 100 && price < 100 {dic[idx][1] = int(math.Ceil(float64(price) * 0.9))}}// 将最终哈希表数据加入lstfor idx, data := range dic {lst = append(lst, []int{idx, data[0], data[1]})}// 对lst排序:先编号升序,再数量降序sort.Slice(lst, func(i, j int) bool {if lst[i][0] != lst[j][0] {return lst[i][0] < lst[j][0]}return lst[i][1] > lst[j][1]})// 输出结果for _, item := range lst {fmt.Printf("%d %d %d\n", item[0], item[1], item[2])}
}
时空复杂度
时间复杂度:O(n)。所有操作都仅需遍历一次数组或者哈希表。
空间复杂度:O(n)。哈希表和列表所占空间。
华为OD算法/大厂面试高频题算法练习冲刺训练
-
华子OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务1000+同学成功上岸!
-
课程讲师为全网200w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
90+天陪伴式学习,100+直播课时,300+动画图解视频,500+LeetCode经典题,500+华为OD真题/大厂真题,还有简历修改、模拟面试、陪伴小群、资深HR对接将为你解锁
-
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
-
可查看链接OD真题汇总(持续更新)
-
绿色聊天软件戳
od1441或了解更多
