返回介绍

solution / 1600-1699 / 1648.Sell Diminishing-Valued Colored Balls / README

发布于 2024-06-17 01:03:16 字数 6283 浏览 0 评论 0 收藏 0

1648. 销售价值减少的颜色球

English Version

题目描述

你有一些球的库存 inventory ,里面包含着不同颜色的球。一个顾客想要 任意颜色 总数为 orders 的球。

这位顾客有一种特殊的方式衡量球的价值:每个球的价值是目前剩下的 同色球 的数目。比方说还剩下 6 个黄球,那么顾客买第一个黄球的时候该黄球的价值为 6 。这笔交易以后,只剩下 5 个黄球了,所以下一个黄球的价值为 5 (也就是球的价值随着顾客购买同色球是递减的)

给你整数数组 inventory ,其中 inventory[i] 表示第 i 种颜色球一开始的数目。同时给你整数 orders ,表示顾客总共想买的球数目。你可以按照 任意顺序 卖球。

请你返回卖了 orders 个球以后 最大 总价值之和。由于答案可能会很大,请你返回答案对 109 + 7 取余数 的结果。

 

示例 1:

输入:inventory = [2,5], orders = 4
输出:14
解释:卖 1 个第一种颜色的球(价值为 2 ),卖 3 个第二种颜色的球(价值为 5 + 4 + 3)。
最大总和为 2 + 5 + 4 + 3 = 14 。

示例 2:

输入:inventory = [3,5], orders = 6
输出:19
解释:卖 2 个第一种颜色的球(价值为 3 + 2),卖 4 个第二种颜色的球(价值为 5 + 4 + 3 + 2)。
最大总和为 3 + 2 + 5 + 4 + 3 + 2 = 19 。

示例 3:

输入:inventory = [2,8,4,10,6], orders = 20
输出:110

示例 4:

输入:inventory = [1000000000], orders = 1000000000
输出:21
解释:卖 1000000000 次第一种颜色的球,总价值为 500000000500000000 。 500000000500000000 对 109 + 7 取余为 21 。

 

提示:

  • 1 <= inventory.length <= 105
  • 1 <= inventory[i] <= 109
  • 1 <= orders <= min(sum(inventory[i]), 109)

解法

方法一:贪心 + 优化模拟

要使得总价值最大,我们可以贪心地每次卖出数量最多的一种颜色的球。由于 orders 值域较大,如果直接简单地模拟,会超时。因此,我们需要优化模拟的过程。

实际上,我们不需要一次次进行模拟,我们可以跟踪数量最多的同色球的种类数 cnt,每一次可以卖出一批球,从而达到加速模拟的目的。

时间复杂度 $O(n\log n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 inventory 的长度。

class Solution:
  def maxProfit(self, inventory: List[int], orders: int) -> int:
    inventory.sort(reverse=True)
    mod = 10**9 + 7
    ans = i = 0
    n = len(inventory)
    while orders > 0:
      while i < n and inventory[i] >= inventory[0]:
        i += 1
      nxt = 0
      if i < n:
        nxt = inventory[i]
      cnt = i
      x = inventory[0] - nxt
      tot = cnt * x
      if tot > orders:
        decr = orders // cnt
        a1, an = inventory[0] - decr + 1, inventory[0]
        ans += (a1 + an) * decr // 2 * cnt
        ans += (inventory[0] - decr) * (orders % cnt)
      else:
        a1, an = nxt + 1, inventory[0]
        ans += (a1 + an) * x // 2 * cnt
        inventory[0] = nxt
      orders -= tot
      ans %= mod
    return ans
class Solution {
  private static final int MOD = (int) 1e9 + 7;

  public int maxProfit(int[] inventory, int orders) {
    Arrays.sort(inventory);
    int n = inventory.length;
    for (int i = 0, j = n - 1; i < j; ++i, --j) {
      int t = inventory[i];
      inventory[i] = inventory[j];
      inventory[j] = t;
    }
    long ans = 0;
    int i = 0;
    while (orders > 0) {
      while (i < n && inventory[i] >= inventory[0]) {
        ++i;
      }
      int nxt = i < n ? inventory[i] : 0;
      int cnt = i;
      long x = inventory[0] - nxt;
      long tot = cnt * x;
      if (tot > orders) {
        int decr = orders / cnt;
        long a1 = inventory[0] - decr + 1, an = inventory[0];
        ans += (a1 + an) * decr / 2 * cnt;
        ans += (a1 - 1) * (orders % cnt);
      } else {
        long a1 = nxt + 1, an = inventory[0];
        ans += (a1 + an) * x / 2 * cnt;
        inventory[0] = nxt;
      }
      orders -= tot;
      ans %= MOD;
    }
    return (int) ans;
  }
}
class Solution {
public:
  int maxProfit(vector<int>& inventory, int orders) {
    long ans = 0, mod = 1e9 + 7;
    int i = 0, n = inventory.size();
    sort(inventory.rbegin(), inventory.rend());
    while (orders > 0) {
      while (i < n && inventory[i] >= inventory[0]) {
        ++i;
      }
      int nxt = i < n ? inventory[i] : 0;
      int cnt = i;
      long x = inventory[0] - nxt;
      long tot = cnt * x;
      if (tot > orders) {
        int decr = orders / cnt;
        long a1 = inventory[0] - decr + 1, an = inventory[0];
        ans += (a1 + an) * decr / 2 * cnt;
        ans += (a1 - 1) * (orders % cnt);
      } else {
        long a1 = nxt + 1, an = inventory[0];
        ans += (a1 + an) * x / 2 * cnt;
        inventory[0] = nxt;
      }
      orders -= tot;
      ans %= mod;
    }
    return ans;
  }
};
func maxProfit(inventory []int, orders int) int {
  var mod int = 1e9 + 7
  i, n, ans := 0, len(inventory), 0
  sort.Ints(inventory)
  for i, j := 0, n-1; i < j; i, j = i+1, j-1 {
    inventory[i], inventory[j] = inventory[j], inventory[i]
  }
  for orders > 0 {
    for i < n && inventory[i] >= inventory[0] {
      i++
    }
    nxt := 0
    if i < n {
      nxt = inventory[i]
    }
    cnt := i
    x := inventory[0] - nxt
    tot := cnt * x
    if tot > orders {
      decr := orders / cnt
      a1, an := inventory[0]-decr+1, inventory[0]
      ans += (a1 + an) * decr / 2 * cnt
      ans += (a1 - 1) * (orders % cnt)
    } else {
      a1, an := nxt+1, inventory[0]
      ans += (a1 + an) * x / 2 * cnt
      inventory[0] = nxt
    }
    orders -= tot
    ans %= mod
  }
  return ans
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文