From 422ccb9b7d01ed56aaa51aea555baa2e12809ad0 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Fri, 18 Aug 2023 19:01:16 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.2819 No.2819.Minimum Relative Loss After Buying Chocolates --- .../README.md | 202 +++++++++++++++++- .../README_EN.md | 186 +++++++++++++++- .../Solution.cpp | 34 +++ .../Solution.go | 32 +++ .../Solution.java | 41 ++++ .../Solution.py | 25 +++ .../Solution.ts | 47 ++++ 7 files changed, 561 insertions(+), 6 deletions(-) create mode 100644 solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.cpp create mode 100644 solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.go create mode 100644 solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.java create mode 100644 solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.py create mode 100644 solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.ts diff --git a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/README.md b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/README.md index 065618e92e034..3f121ca2eea01 100644 --- a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/README.md +++ b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/README.md @@ -70,6 +70,22 @@ It can be shown that these are the minimum possible relative losses. +**方法一:排序 + 二分查找 + 前缀和** + +根据题目描述,我们可以知道: + +如果 $prices[i] \leq k$,那么 Bob 需要支付 $prices[i]$,而 Alice 不需要支付。因此 Bob 的相对损失为 $prices[i]$。在这种情况下,Bob 应该选择价格较低的巧克力,才能最小化相对损失。 + +如果 $prices[i] \gt k$,那么 Bob 需要支付 $k$,而 Alice 需要支付 $prices[i] - k$。因此 Bob 的相对损失为 $k - (prices[i] - k) = 2k - prices[i]$。在这种情况下,Bob 应该选择价格较高的巧克力,才能最小化相对损失。 + +因此,我们先对价格数组 $prices$ 进行排序,然后预处理出前缀和数组 $s$,其中 $s[i]$ 表示前 $i$ 个巧克力的价格之和。 + +接下来,对于每个询问 $[k, m]$,我们先使用二分查找,找到第一个价格大于 $k$ 的巧克力的下标 $r$。然后,再利用二分查找,找到左侧应该选择的巧克力的数量 $l$,那么右侧应该选择的巧克力的数量就是 $m - l$。此时,Bob 的相对损失为 $s[l] + 2k(m - l) - (s[n] - s[n - (m - l)])$。 + +上述第二次二分查找的过程中,我们需要判断 $prices[mid] \lt 2k - prices[n - (m - mid)]$,其中 $right$ 表示右侧应该选择的巧克力的数量。如果该不等式成立,那么说明选择 $mid$ 位置的巧克力的相对损失较低,此时更新 $l = mid + 1$。否则,说明 $mid$ 位置的巧克力的相对损失较高,此时更新 $r = mid$。 + +时间复杂度 $O((n + m) \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是数组 $prices$ 和 $queries$ 的长度。 + ### **Python3** @@ -77,7 +93,31 @@ It can be shown that these are the minimum possible relative losses. ```python - +class Solution: + def minimumRelativeLosses( + self, prices: List[int], queries: List[List[int]] + ) -> List[int]: + def f(k: int, m: int) -> int: + l, r = 0, min(m, bisect_right(prices, k)) + while l < r: + mid = (l + r) >> 1 + right = m - mid + if prices[mid] < 2 * k - prices[n - right]: + l = mid + 1 + else: + r = mid + return l + + prices.sort() + s = list(accumulate(prices, initial=0)) + ans = [] + n = len(prices) + for k, m in queries: + l = f(k, m) + r = m - l + loss = s[l] + 2 * k * r - (s[n] - s[n - r]) + ans.append(loss) + return ans ``` ### **Java** @@ -85,19 +125,175 @@ It can be shown that these are the minimum possible relative losses. ```java - +class Solution { + private int n; + private int[] prices; + + public long[] minimumRelativeLosses(int[] prices, int[][] queries) { + n = prices.length; + Arrays.sort(prices); + this.prices = prices; + long[] s = new long[n + 1]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + prices[i]; + } + int q = queries.length; + long[] ans = new long[q]; + for (int i = 0; i < q; ++i) { + int k = queries[i][0], m = queries[i][1]; + int l = f(k, m); + int r = m - l; + ans[i] = s[l] + 2L * k * r - (s[n] - s[n - r]); + } + return ans; + } + + private int f(int k, int m) { + int l = 0, r = Arrays.binarySearch(prices, k); + if (r < 0) { + r = -(r + 1); + } + r = Math.min(m, r); + while (l < r) { + int mid = (l + r) >> 1; + int right = m - mid; + if (prices[mid] < 2L * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + } +} ``` ### **C++** ```cpp - +class Solution { +public: + vector minimumRelativeLosses(vector& prices, vector>& queries) { + int n = prices.size(); + sort(prices.begin(), prices.end()); + long long s[n + 1]; + s[0] = 0; + for (int i = 1; i <= n; ++i) { + s[i] = s[i - 1] + prices[i - 1]; + } + auto f = [&](int k, int m) { + int l = 0, r = upper_bound(prices.begin(), prices.end(), k) - prices.begin(); + r = min(r, m); + while (l < r) { + int mid = (l + r) >> 1; + int right = m - mid; + if (prices[mid] < 2LL * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + }; + vector ans; + for (auto& q : queries) { + int k = q[0], m = q[1]; + int l = f(k, m); + int r = m - l; + ans.push_back(s[l] + 2LL * k * r - (s[n] - s[n - r])); + } + return ans; + } +}; ``` ### **Go** ```go +func minimumRelativeLosses(prices []int, queries [][]int) []int64 { + n := len(prices) + sort.Ints(prices) + s := make([]int, n+1) + for i, x := range prices { + s[i+1] = s[i] + x + } + f := func(k, m int) int { + l, r := 0, sort.Search(n, func(i int) bool { return prices[i] > k }) + if r > m { + r = m + } + for l < r { + mid := (l + r) >> 1 + right := m - mid + if prices[mid] < 2*k-prices[n-right] { + l = mid + 1 + } else { + r = mid + } + } + return l + } + ans := make([]int64, len(queries)) + for i, q := range queries { + k, m := q[0], q[1] + l := f(k, m) + r := m - l + ans[i] = int64(s[l] + 2*k*r - (s[n] - s[n-r])) + } + return ans +} +``` +### **TypeScript** + +```ts +function minimumRelativeLosses( + prices: number[], + queries: number[][], +): number[] { + const n = prices.length; + prices.sort((a, b) => a - b); + const s: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + s[i + 1] = s[i] + prices[i]; + } + + const search = (x: number): number => { + let l = 0; + let r = n; + while (l < r) { + const mid = (l + r) >> 1; + if (prices[mid] > x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + + const f = (k: number, m: number): number => { + let l = 0; + let r = Math.min(search(k), m); + while (l < r) { + const mid = (l + r) >> 1; + const right = m - mid; + if (prices[mid] < 2 * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + }; + const ans: number[] = []; + for (const [k, m] of queries) { + const l = f(k, m); + const r = m - l; + ans.push(s[l] + 2 * k * r - (s[n] - s[n - r])); + } + return ans; +} ``` ### **...** diff --git a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/README_EN.md b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/README_EN.md index 7fa53213dd5bb..7bbf039d198ef 100644 --- a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/README_EN.md +++ b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/README_EN.md @@ -71,25 +71,205 @@ It can be shown that these are the minimum possible relative losses. ### **Python3** ```python - +class Solution: + def minimumRelativeLosses( + self, prices: List[int], queries: List[List[int]] + ) -> List[int]: + def f(k: int, m: int) -> int: + l, r = 0, min(m, bisect_right(prices, k)) + while l < r: + mid = (l + r) >> 1 + right = m - mid + if prices[mid] < 2 * k - prices[n - right]: + l = mid + 1 + else: + r = mid + return l + + prices.sort() + s = list(accumulate(prices, initial=0)) + ans = [] + n = len(prices) + for k, m in queries: + l = f(k, m) + r = m - l + loss = s[l] + 2 * k * r - (s[n] - s[n - r]) + ans.append(loss) + return ans ``` ### **Java** ```java - +class Solution { + private int n; + private int[] prices; + + public long[] minimumRelativeLosses(int[] prices, int[][] queries) { + n = prices.length; + Arrays.sort(prices); + this.prices = prices; + long[] s = new long[n + 1]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + prices[i]; + } + int q = queries.length; + long[] ans = new long[q]; + for (int i = 0; i < q; ++i) { + int k = queries[i][0], m = queries[i][1]; + int l = f(k, m); + int r = m - l; + ans[i] = s[l] + 2L * k * r - (s[n] - s[n - r]); + } + return ans; + } + + private int f(int k, int m) { + int l = 0, r = Arrays.binarySearch(prices, k); + if (r < 0) { + r = -(r + 1); + } + r = Math.min(m, r); + while (l < r) { + int mid = (l + r) >> 1; + int right = m - mid; + if (prices[mid] < 2L * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + } +} ``` ### **C++** ```cpp - +class Solution { +public: + vector minimumRelativeLosses(vector& prices, vector>& queries) { + int n = prices.size(); + sort(prices.begin(), prices.end()); + long long s[n + 1]; + s[0] = 0; + for (int i = 1; i <= n; ++i) { + s[i] = s[i - 1] + prices[i - 1]; + } + auto f = [&](int k, int m) { + int l = 0, r = upper_bound(prices.begin(), prices.end(), k) - prices.begin(); + r = min(r, m); + while (l < r) { + int mid = (l + r) >> 1; + int right = m - mid; + if (prices[mid] < 2LL * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + }; + vector ans; + for (auto& q : queries) { + int k = q[0], m = q[1]; + int l = f(k, m); + int r = m - l; + ans.push_back(s[l] + 2LL * k * r - (s[n] - s[n - r])); + } + return ans; + } +}; ``` ### **Go** ```go +func minimumRelativeLosses(prices []int, queries [][]int) []int64 { + n := len(prices) + sort.Ints(prices) + s := make([]int, n+1) + for i, x := range prices { + s[i+1] = s[i] + x + } + f := func(k, m int) int { + l, r := 0, sort.Search(n, func(i int) bool { return prices[i] > k }) + if r > m { + r = m + } + for l < r { + mid := (l + r) >> 1 + right := m - mid + if prices[mid] < 2*k-prices[n-right] { + l = mid + 1 + } else { + r = mid + } + } + return l + } + ans := make([]int64, len(queries)) + for i, q := range queries { + k, m := q[0], q[1] + l := f(k, m) + r := m - l + ans[i] = int64(s[l] + 2*k*r - (s[n] - s[n-r])) + } + return ans +} +``` +### **TypeScript** + +```ts +function minimumRelativeLosses( + prices: number[], + queries: number[][], +): number[] { + const n = prices.length; + prices.sort((a, b) => a - b); + const s: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + s[i + 1] = s[i] + prices[i]; + } + + const search = (x: number): number => { + let l = 0; + let r = n; + while (l < r) { + const mid = (l + r) >> 1; + if (prices[mid] > x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + + const f = (k: number, m: number): number => { + let l = 0; + let r = Math.min(search(k), m); + while (l < r) { + const mid = (l + r) >> 1; + const right = m - mid; + if (prices[mid] < 2 * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + }; + const ans: number[] = []; + for (const [k, m] of queries) { + const l = f(k, m); + const r = m - l; + ans.push(s[l] + 2 * k * r - (s[n] - s[n - r])); + } + return ans; +} ``` ### **...** diff --git a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.cpp b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.cpp new file mode 100644 index 0000000000000..7e6c457543816 --- /dev/null +++ b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.cpp @@ -0,0 +1,34 @@ +class Solution { +public: + vector minimumRelativeLosses(vector& prices, vector>& queries) { + int n = prices.size(); + sort(prices.begin(), prices.end()); + long long s[n + 1]; + s[0] = 0; + for (int i = 1; i <= n; ++i) { + s[i] = s[i - 1] + prices[i - 1]; + } + auto f = [&](int k, int m) { + int l = 0, r = upper_bound(prices.begin(), prices.end(), k) - prices.begin(); + r = min(r, m); + while (l < r) { + int mid = (l + r) >> 1; + int right = m - mid; + if (prices[mid] < 2LL * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + }; + vector ans; + for (auto& q : queries) { + int k = q[0], m = q[1]; + int l = f(k, m); + int r = m - l; + ans.push_back(s[l] + 2LL * k * r - (s[n] - s[n - r])); + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.go b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.go new file mode 100644 index 0000000000000..1ad9840903faa --- /dev/null +++ b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.go @@ -0,0 +1,32 @@ +func minimumRelativeLosses(prices []int, queries [][]int) []int64 { + n := len(prices) + sort.Ints(prices) + s := make([]int, n+1) + for i, x := range prices { + s[i+1] = s[i] + x + } + f := func(k, m int) int { + l, r := 0, sort.Search(n, func(i int) bool { return prices[i] > k }) + if r > m { + r = m + } + for l < r { + mid := (l + r) >> 1 + right := m - mid + if prices[mid] < 2*k-prices[n-right] { + l = mid + 1 + } else { + r = mid + } + } + return l + } + ans := make([]int64, len(queries)) + for i, q := range queries { + k, m := q[0], q[1] + l := f(k, m) + r := m - l + ans[i] = int64(s[l] + 2*k*r - (s[n] - s[n-r])) + } + return ans +} \ No newline at end of file diff --git a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.java b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.java new file mode 100644 index 0000000000000..5f0499959a254 --- /dev/null +++ b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.java @@ -0,0 +1,41 @@ +class Solution { + private int n; + private int[] prices; + + public long[] minimumRelativeLosses(int[] prices, int[][] queries) { + n = prices.length; + Arrays.sort(prices); + this.prices = prices; + long[] s = new long[n + 1]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + prices[i]; + } + int q = queries.length; + long[] ans = new long[q]; + for (int i = 0; i < q; ++i) { + int k = queries[i][0], m = queries[i][1]; + int l = f(k, m); + int r = m - l; + ans[i] = s[l] + 2L * k * r - (s[n] - s[n - r]); + } + return ans; + } + + private int f(int k, int m) { + int l = 0, r = Arrays.binarySearch(prices, k); + if (r < 0) { + r = -(r + 1); + } + r = Math.min(m, r); + while (l < r) { + int mid = (l + r) >> 1; + int right = m - mid; + if (prices[mid] < 2L * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + } +} \ No newline at end of file diff --git a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.py b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.py new file mode 100644 index 0000000000000..9cc30b5b2f80a --- /dev/null +++ b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.py @@ -0,0 +1,25 @@ +class Solution: + def minimumRelativeLosses( + self, prices: List[int], queries: List[List[int]] + ) -> List[int]: + def f(k: int, m: int) -> int: + l, r = 0, min(m, bisect_right(prices, k)) + while l < r: + mid = (l + r) >> 1 + right = m - mid + if prices[mid] < 2 * k - prices[n - right]: + l = mid + 1 + else: + r = mid + return l + + prices.sort() + s = list(accumulate(prices, initial=0)) + ans = [] + n = len(prices) + for k, m in queries: + l = f(k, m) + r = m - l + loss = s[l] + 2 * k * r - (s[n] - s[n - r]) + ans.append(loss) + return ans diff --git a/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.ts b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.ts new file mode 100644 index 0000000000000..0b1a73a01f3f2 --- /dev/null +++ b/solution/2800-2899/2819.Minimum Relative Loss After Buying Chocolates/Solution.ts @@ -0,0 +1,47 @@ +function minimumRelativeLosses( + prices: number[], + queries: number[][], +): number[] { + const n = prices.length; + prices.sort((a, b) => a - b); + const s: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + s[i + 1] = s[i] + prices[i]; + } + + const search = (x: number): number => { + let l = 0; + let r = n; + while (l < r) { + const mid = (l + r) >> 1; + if (prices[mid] > x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + + const f = (k: number, m: number): number => { + let l = 0; + let r = Math.min(search(k), m); + while (l < r) { + const mid = (l + r) >> 1; + const right = m - mid; + if (prices[mid] < 2 * k - prices[n - right]) { + l = mid + 1; + } else { + r = mid; + } + } + return l; + }; + const ans: number[] = []; + for (const [k, m] of queries) { + const l = f(k, m); + const r = m - l; + ans.push(s[l] + 2 * k * r - (s[n] - s[n - r])); + } + return ans; +}