2023-04-02:设计一个仓库管理器,提供如下的方法:

  1. void supply(String item, int num, int price)
    名字叫item的商品,个数num,价格price。
  2. int sell(String item, int num)
    卖出叫item的商品,个数num个,价格从低到高,返回卖出总价。
    如果商品很多,每种商品的数量可能很多,该怎么设计这个结构。

答案2023-04-02:

设计思路

我们需要设计一个仓库管理器,它可以支持以下几种操作:

1.向指定商品中进货一定数量的货物;
2.对指定商品进行售卖,并返回售卖的总价。

为了实现这些功能,我们需要对每种商品维护一个最大堆,堆中存储的是该商品的所有不同价格,按照从低到高的顺序排列。同时,我们还需要一个哈希表,记录每个价格对应的商品数量。

在进货时,我们首先根据传入的商品名称,在哈希表中查找是否已经有该商品信息。如果有,则直接将新货物数量加入相应的价格中;否则,我们就需要创建一个新的最大堆和哈希表项,并将新货物信息添加到其中。

在售卖时,我们需要按照从低到高的价格顺序逐个处理商品。具体来说,我们从最大堆中弹出最低价格的商品,然后查询其数量是否足够售卖。如果数量足够,那么我们将相应的金额累加到总价中,并从哈希表中删除对应的价格项;否则,我们只能将部分商品出售,并将剩余商品放回最大堆中,等待下一次处理。

主要数据结构

为了实现上述功能,我们需要使用以下几种数据结构:

1.哈希表(HashMap):用于记录每个商品的价格和数量信息;
2.最大堆(BinaryHeap):存储每个商品的所有不同价格,并按照从低到高的顺序排列。

具体实现

在 Rust 中,我们可以通过定义一个名为 Store 的结构体来表示每种商品的价格数量信息。该结构体包含两个字段:

1.price_nums:本质上是一个哈希表,记录了每个价格对应的商品数量;
2.heap:是一个最大堆,存储了所有不同价格的商品,便于在售卖时按照价格从低到高进行处理。

struct Store {
price_nums: HashMap<i32, i32>,
heap: BinaryHeap<i32>,
} impl Store {
fn new() -> Self {
Self {
price_nums: HashMap::new(),
heap: BinaryHeap::new(),
}
} fn add(&mut self, num: i32, price: i32) {
if let Some(count) = self.price_nums.get_mut(&price) {
*count += num;
} else {
self.price_nums.insert(price, num);
self.heap.push(price);
}
} fn remove(&mut self, mut num: i32) -> i32 {
let mut money = 0;
while !self.heap.is_empty() && num != 0 {
let price = self.heap.pop().unwrap();
let stores = *self.price_nums.get(&price).unwrap(); if num >= stores {
money += price * stores;
self.price_nums.remove(&price);
num -= stores;
} else {
money += price * num;
self.heap.push(price);
self.price_nums.insert(price, stores - num);
break;
}
}
money
}
}

接下来,我们可以定义一个名为 StoreManager 的结构体,用于管理所有商品的进货和售出操作。该结构体包含一个哈希表 map,键是商品名称,值是对应的 Store 对象。

pub struct StoreManager {
map: HashMap<String, Store>,
}

在 supply 方法中,我们根据传入的商品名称在哈希表中查找是否已经有该商品信息。如果有,则直接将新货物数量加入相应的价格中;否则,我们就需要创建一个新的最大堆和哈希表项,并将新货物信息添加到其中。

在 sell 方法中,我们首先通过商品名称找到对应的 Store 对象,然后调用其 remove 方法进行售卖操作。在这个方法里,我们首先从最大堆中弹出价格最低的商品,然后查看其数量是否足够售卖。如果该商品数量大于等于需要售卖的数量,那么直接将总价增加相应的金额,并删除该商品;否则将总价增加当前售卖所需的金额,并将剩余的商品放回最大堆中。

impl StoreManager {
pub fn supply(&mut self, item: &str, num: i32, price: i32) {
let store = self.map.entry(item.to_string()).or_insert(Store::new());
store.add(num, price);
} pub fn sell(&mut self, item: &str, num: i32) -> i32 {
self.map.get_mut(item).unwrap().remove(num)
}
}

rust完整代码

use std::collections::{BinaryHeap, HashMap};

struct Store {
price_nums: HashMap<i32, i32>,
heap: BinaryHeap<i32>,
} impl Store {
fn new() -> Self {
Self {
price_nums: HashMap::new(),
heap: BinaryHeap::new(),
}
} fn add(&mut self, num: i32, price: i32) {
if let Some(count) = self.price_nums.get_mut(&price) {
*count += num;
} else {
self.price_nums.insert(price, num);
self.heap.push(price);
}
} fn remove(&mut self, mut num: i32) -> i32 {
let mut money = 0;
while !self.heap.is_empty() && num != 0 {
let price = self.heap.pop().unwrap();
let stores = *self.price_nums.get(&price).unwrap(); if num >= stores {
money += price * stores;
self.price_nums.remove(&price);
num -= stores;
} else {
money += price * num;
self.heap.push(price);
self.price_nums.insert(price, stores - num);
break;
}
}
money
}
} pub struct StoreManager {
map: HashMap<String, Store>,
} impl StoreManager {
pub fn new() -> Self {
Self {
map: HashMap::new(),
}
} pub fn supply(&mut self, item: &str, num: i32, price: i32) {
let store = self.map.entry(item.to_string()).or_insert(Store::new());
store.add(num, price);
} pub fn sell(&mut self, item: &str, num: i32) -> i32 {
self.map.get_mut(item).unwrap().remove(num)
}
}
fn main() {
let mut manager = StoreManager::new(); manager.supply("apple", 10, 3);
manager.supply("banana", 5, 2);
manager.supply("orange", 8, 4); let total_price = manager.sell("banana", 3);
println!("Sell 3 bananas: ${}", total_price); let total_price = manager.sell("banana", 2);
println!("Sell 2 bananas: ${}", total_price); let total_price = manager.sell("apple", 5);
println!("Sell 5 apples: ${}", total_price); let total_price = manager.sell("orange", 10);
println!("Sell 10 oranges: ${}", total_price);
}

2023-04-02:设计一个仓库管理器,提供如下的方法: 1) void supply(String item, int num, int price) 名字叫item的商品,个数num,价格pri的更多相关文章

  1. 设计一个缓存器 ReadLock提高性能

    /** * * @描述: 设计一个缓存器 ReadLock提高性能. * @作者: Wnj . * @创建时间: 2017年5月16日 . * @版本: 1.0 . */ public class C ...

  2. Light Pre-Pass 渲染器----为多光源设计一个渲染器

    http://blog.csdn.net/xoyojank/article/details/4460953 作者: Wolfgang Engel, 原文: http://www.wolfgang-en ...

  3. 2018/04/02 每日一个Linux命令 之 新建/修改/删除群组

    -- 新建群组 groupadd [群组名] -- 修改群组名称 groupmod [群组名] [新群组名] -n 修改组名 -g 修改组识别码 -- 删除群组 groupdel [删除的组名] --

  4. ubuntu12.04打开某一个已安装的软件的方法

    1.快捷键win+A,里面显示已安装的软件 2.打开左上角的dash home,即ubuntu标志图,输入想要打开的软件 还有其它方法,探索中... .

  5. 使用仓库管理器——Sonatype Nexus的九大理由

    目前有很多组织使用了一些工具依赖于Maven仓库,但他们并没有采用一个仓库管理器,对于这一点我十分惊讶.可能没人提出来这一点,没人站出来告诉别人使用一个仓库管理器能带来什么好处.我经常能从很多不使用M ...

  6. java开发中的链式思维 —— 设计一个链式过滤器

    概述 最近在弄阿里云的sls日志服务,该服务提供了一个搜索接口,可根据各种运算.逻辑等表达式搜出想要的内容.具体语法可见https://help.aliyun.com/document_detail/ ...

  7. 「造个轮子」——cicada 设计一个配置模块

    前言 在前两次的 cicada 版本中其实还不支持读取配置文件,比如对端口.路由的配置. 因此我按照自己的想法创建了一个 issue ,也收集到了一些很不错的建议. 最终其实还是按照我之前的想法来做了 ...

  8. 【Android Developers Training】 94. 创建一个空内容提供器(Content Provider)

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  9. 框架源码系列四:手写Spring-配置(为什么要提供配置的方法、选择什么样的配置方式、配置方式的工作过程是怎样的、分步骤一个一个的去分析和设计)

    一.为什么要提供配置的方法 经过前面的手写Spring IOC.手写Spring DI.手写Spring AOP,我们知道要创建一个bean对象,需要用户先定义好bean,然后注册到bean工厂才能创 ...

  10. 设计一个简单的,低耗的能够区分红酒和白酒的感知器(sensor)

    学习using weka in your javacode 主要学习两个部分的代码:1.过滤数据集 2 使用J48决策树进行分类.下面的例子没有对数据集进行分割,完全使用训练集作为测试集,所以不符合数 ...

随机推荐

  1. setTimeout的那些事

      一.我们可以设置一个定时器用以指定某个程序在指定时间后才执行 1 setTimeout(function(){ 2 console.log("do something"); 3 ...

  2. python 引用传递,简单例子

    from threading import Threaddef test1(a): while 1: print adef test2(a): a["a"] = 2if __nam ...

  3. Spring--事务案例的实现

    案例实现(主要是想用Spring实现一下MyBatis的相关内容) JDBCConfig.java MyBatisConfig.java SpringConfig.java accountDao.ja ...

  4. J - Straight Master Gym - 101775J 差分

    题意:纸牌顺子:连续的3张或连续的4张或连续的5张为顺子.手中的牌共有n个数字,每个数字是a[i]个,能不能把手中所有的牌都是属于顺子. 1 ≤ T ≤ 100. 1 ≤ N ≤ 2 × 105. 0 ...

  5. 基于 Gitlab + Harbor + K8s + Kuboard 的 CI 实践

    CI/CD 概念 CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法.CI/CD 的核心概念是持续集成.持续交付和持续部署.作为一种面向开发和运维团队的解决方案,CI/CD 主要 ...

  6. 从零开始学习Java系列教程之Windos下dos命令行使用详解前言

    在上一篇文章中,壹哥重点给大家讲解了Java开发和运行环境的安装及配置,分析了JDK与JRE的区别,而且还给大家提到了dos命令行.可能有些童鞋对dos命令的使用还不熟悉,其实我们在初学Java时,经 ...

  7. Java 面试——Zookeeper

    一.Zookeeper 实现机制 文件系统 + 通知机制 二.Zookeeper 高可用实现原理 一个 ZooKeeper 集群如果要对外提供可用的服务,那么集群中必须要有过半的机器正常工作并且彼此之 ...

  8. 全局唯一ID的实现方案

    为什么需要保证唯一ID? 在单机服务架构中,数据库的每一个业务表的主键ID都是允许自增的,但是在分布式服务架构的分库分表的设计,使得多个库或者多个表存储了相同的业务表,如果没有一个全局的唯一ID设计方 ...

  9. [CTF]picoCTF-day1

    Lets Warm Up If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCI ...

  10. 中心极限定理的模拟—R实现

    中心极限定理,是指概率论中讨论随机变量序列部分和分布渐近于正态分布的一类定理.这组定理是数理统计学和误差分析的理论基础,指出了大量随机变量近似服从正态分布的条件.它是概率论中最重要的一类定理,有广泛的 ...