LeetCode 银联-4. 设计自动售货机

力扣

 

【哈希表+优先队列】这道题说实话是不难的,用哈希表记录每个人的折扣,再用哈希表记录每种商品的名称和同名商品商品信息的优先队列,队列中按照价格排序,价格相同按照过期时间点排序。插入操作就完成了。

购买时:挨个弹出队列中的内容,如果当前商品过期,直接删除不用管了,因为题目中时间点是非递减的,过期的商品以后再也用不到了。验证商品数量num和要购买的数量number的关系,如果数量不够,就全买下,把number-num,然后还要把商品放到list中(防止最后买不了回滚),再继续弹出下一个验证。如果商品数量=要购买的数量,说明一定可以购买成功,break就行了。如果商品数量>剩余要购买的数量,说明可以购买成功,需要把当前这个商品的num设置为num-number,然后放进rem列表中。直到队列中的商品全部都被遍历过了。

如果最后number为0,说明可以购买成功,把rem中的再加回去;如果number不为0,说明不能购买成功,把list中的回滚回去。

class Goods {
    public int time;
    public int end;
    public int num;
    public int price;
    public String item;
    Goods(int t, int e, int n, int p, String it) {
        end = e; num = n; price = p; item = it; time = t;
    } 
    void setNum(int n) {
        num = n;
    } 
    public String toString() {
        return item + "," + price + "," + end + "," + num;
    }
}

class VendingMachine {
    
    Map<String, PriorityQueue<Goods>> map = new HashMap();
    Map<String, Integer> cut = new HashMap();
    
    // PriorityQueue<Goods> queue = new PriorityQueue<Goods>((a, b) -> {
    //     if (a.price < b.price) return -1;
    //     if (a.end < b.end) return -1;
    //     return 1;
    // });

    public VendingMachine() {
        
    }
    
    public void addItem(int time, int number, String item, int price, int duration) {
        if (!map.containsKey(item)) {
            PriorityQueue<Goods> queue = new PriorityQueue<Goods>((a, b) -> {
                // if (a.price == b.price) return a.end - b.end;
                if (a.price < b.price) return -1;
                if (a.price == b.price && a.end < b.end) return -1;
                return 1;
                // return a.price - b.price;
            });
            map.put(item, queue);
        }
        map.get(item).offer(new Goods(time, time + duration, number, price, item)); 
        // System.out.println(map.get(item).size());
    }
    
    public long sell(int time, String customer, String item, int number) {
        if (!cut.containsKey(customer)) {
            cut.put(customer, 100);
        }
        int c = cut.get(customer);
        if (!map.containsKey(item)) return -1;
        PriorityQueue<Goods> queue = map.get(item);
        double price = 0;
        List<Goods> list = new ArrayList();
        List<Goods> rem = new ArrayList();
        // while (!queue.isEmpty()) {
        //     Goods goods = queue.poll();
        //     System.out.println(goods.toString());
        // }
        while (!queue.isEmpty()) {
            Goods goods = queue.poll();
            // System.out.println(goods.toString());
            if (goods.time > time) {
                 continue;
            }
            if (goods.end < time) {
                continue;
            } else {
                if (goods.num >= number) {
                    if (goods.num == number) {
                        price += (double)number * goods.price;
                        number = 0; break;
                    } else {
                        goods.setNum(goods.num - number);
                        price += (double)number * goods.price;
                        rem.add(goods);
                        number = 0; break;
                    }
                } else {
                    list.add(goods);
                    price += (double)goods.num * goods.price;
                    number -= goods.num;
                }
            }
        }
        
            // System.out.println("****by******" + number + "," + price);
        if (number == 0) {
            cut.put(customer, Math.max(30, cut.get(customer) - 1));
            for (var goods: rem) queue.offer(goods);
            // for (var goods: list) queue.offer(goods);
            // System.out.println(price);
            return (long)((price * c + 100 - 1) / 100);
        } else {
            for (var goods: list) queue.offer(goods);
            return -1;
        }
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值