From 5baf49a3cf301802f5c17205815b58664bb8f55d Mon Sep 17 00:00:00 2001 From: yanglbme Date: Wed, 12 Feb 2025 08:35:10 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.1760 No.1760.Minimum Limit of Balls in a Bag --- .../README.md | 148 +++++++++++------ .../README_EN.md | 152 ++++++++++++------ .../Solution.cpp | 20 +-- .../Solution.cs | 18 +++ .../Solution.go | 8 +- .../Solution.java | 23 ++- .../Solution.js | 20 +-- .../Solution.py | 2 +- .../Solution.rs | 23 +++ .../Solution.ts | 20 +-- 10 files changed, 280 insertions(+), 154 deletions(-) create mode 100644 solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.cs create mode 100644 solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.rs diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/README.md b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/README.md index 62765638217de..919bf3c866941 100644 --- a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/README.md +++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/README.md @@ -87,9 +87,15 @@ tags: ### 方法一:二分查找 -我们可以将题目可以转换为:对某个开销值,看它能不能在 maxOperations 次操作内得到。因此,二分枚举开销值,找到最小的且满足条件的开销值即可。 +本题需要我们最小化开销,即最小化单个袋子里球数目的最大值。随着最大值的增大,操作次数会减少,越容易满足条件。 -时间复杂度 $O(n \times \log M)$。其中 $n$ 和 $M$ 分别为数组 `nums` 的长度和最大值。 +因此,我们可以二分枚举单个袋子里球数目的最大值,判断是否能在 $\textit{maxOperations}$ 次操作内得到。 + +具体地,我们定义二分查找的左边界 $l = 1$,右边界 $r = \max(\textit{nums})$。然后我们不断二分枚举中间值 $\textit{mid} = \frac{l + r}{2}$,对于每个 $\textit{mid}$,我们计算在这个 $\textit{mid}$ 下,需要的操作次数。如果操作次数小于等于 $\textit{maxOperations}$,说明 $\textit{mid}$ 满足条件,我们将右边界 $r$ 更新为 $\textit{mid}$,否则将左边界 $l$ 更新为 $\textit{mid} + 1$。 + +最后,我们返回左边界 $l$ 即可。 + +时间复杂度 $O(n \times \log M)$,其中 $n$ 和 $M$ 分别是数组 $\textit{nums}$ 的长度和最大值。空间复杂度 $O(1)$。 @@ -101,7 +107,7 @@ class Solution: def check(mx: int) -> bool: return sum((x - 1) // mx for x in nums) <= maxOperations - return bisect_left(range(1, max(nums)), True, key=check) + 1 + return bisect_left(range(1, max(nums) + 1), True, key=check) + 1 ``` #### Java @@ -109,23 +115,20 @@ class Solution: ```java class Solution { public int minimumSize(int[] nums, int maxOperations) { - int left = 1, right = 0; - for (int x : nums) { - right = Math.max(right, x); - } - while (left < right) { - int mid = (left + right) >> 1; - long cnt = 0; + int l = 1, r = Arrays.stream(nums).max().getAsInt(); + while (l < r) { + int mid = (l + r) >> 1; + long s = 0; for (int x : nums) { - cnt += (x - 1) / mid; + s += (x - 1) / mid; } - if (cnt <= maxOperations) { - right = mid; + if (s <= maxOperations) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return left; + return l; } } ``` @@ -136,20 +139,20 @@ class Solution { class Solution { public: int minimumSize(vector& nums, int maxOperations) { - int left = 1, right = *max_element(nums.begin(), nums.end()); - while (left < right) { - int mid = (left + right) >> 1; - long long cnt = 0; + int l = 1, r = ranges::max(nums); + while (l < r) { + int mid = (l + r) >> 1; + long long s = 0; for (int x : nums) { - cnt += (x - 1) / mid; + s += (x - 1) / mid; } - if (cnt <= maxOperations) { - right = mid; + if (s <= maxOperations) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return left; + return l; } }; ``` @@ -161,11 +164,11 @@ func minimumSize(nums []int, maxOperations int) int { r := slices.Max(nums) return 1 + sort.Search(r, func(mx int) bool { mx++ - cnt := 0 + s := 0 for _, x := range nums { - cnt += (x - 1) / mx + s += (x - 1) / mx } - return cnt <= maxOperations + return s <= maxOperations }) } ``` @@ -174,21 +177,45 @@ func minimumSize(nums []int, maxOperations int) int { ```ts function minimumSize(nums: number[], maxOperations: number): number { - let left = 1; - let right = Math.max(...nums); - while (left < right) { - const mid = (left + right) >> 1; - let cnt = 0; - for (const x of nums) { - cnt += ~~((x - 1) / mid); - } - if (cnt <= maxOperations) { - right = mid; + let [l, r] = [1, Math.max(...nums)]; + while (l < r) { + const mid = (l + r) >> 1; + const s = nums.map(x => ((x - 1) / mid) | 0).reduce((a, b) => a + b); + if (s <= maxOperations) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return left; + return l; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn minimum_size(nums: Vec, max_operations: i32) -> i32 { + let mut l = 1; + let mut r = *nums.iter().max().unwrap(); + + while l < r { + let mid = (l + r) / 2; + let mut s: i64 = 0; + + for &x in &nums { + s += ((x - 1) / mid) as i64; + } + + if s <= max_operations as i64 { + r = mid; + } else { + l = mid + 1; + } + } + + l + } } ``` @@ -201,24 +228,43 @@ function minimumSize(nums: number[], maxOperations: number): number { * @return {number} */ var minimumSize = function (nums, maxOperations) { - let left = 1; - let right = Math.max(...nums); - while (left < right) { - const mid = (left + right) >> 1; - let cnt = 0; - for (const x of nums) { - cnt += ~~((x - 1) / mid); - } - if (cnt <= maxOperations) { - right = mid; + let [l, r] = [1, Math.max(...nums)]; + while (l < r) { + const mid = (l + r) >> 1; + const s = nums.map(x => ((x - 1) / mid) | 0).reduce((a, b) => a + b); + if (s <= maxOperations) { + r = mid; } else { - left = mid + 1; + l = mid + 1; } } - return left; + return l; }; ``` +#### C# + +```cs +public class Solution { + public int MinimumSize(int[] nums, int maxOperations) { + int l = 1, r = nums.Max(); + while (l < r) { + int mid = (l + r) >> 1; + long s = 0; + foreach (int x in nums) { + s += (x - 1) / mid; + } + if (s <= maxOperations) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + } +} +``` + diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/README_EN.md b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/README_EN.md index 476f69ff11d86..4a2d5253401f5 100644 --- a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/README_EN.md +++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/README_EN.md @@ -43,7 +43,7 @@ tags:
 Input: nums = [9], maxOperations = 2
 Output: 3
-Explanation: 
+Explanation:
 - Divide the bag with 9 balls into two bags of sizes 6 and 3. [9] -> [6,3].
 - Divide the bag with 6 balls into two bags of sizes 3 and 3. [6,3] -> [3,3,3].
 The bag with the most number of balls has 3 balls, so your penalty is 3 and you should return 3.
@@ -76,7 +76,17 @@ The bag with the most number of balls has 2 balls, so your penalty is 2, and you
 
 
 
-### Solution 1
+### Solution 1: Binary Search
+
+This problem requires us to minimize the cost, which is the maximum number of balls in a single bag. As the maximum value increases, the number of operations decreases, making it easier to meet the condition.
+
+Therefore, we can use binary search to enumerate the maximum number of balls in a single bag and determine if it can be achieved within $\textit{maxOperations}$ operations.
+
+Specifically, we define the left boundary of the binary search as $l = 1$ and the right boundary as $r = \max(\textit{nums})$. Then we continuously perform binary search on the middle value $\textit{mid} = \frac{l + r}{2}$. For each $\textit{mid}$, we calculate the number of operations needed. If the number of operations is less than or equal to $\textit{maxOperations}$, it means $\textit{mid}$ meets the condition, and we update the right boundary $r$ to $\textit{mid}$. Otherwise, we update the left boundary $l$ to $\textit{mid} + 1$.
+
+Finally, we return the left boundary $l$.
+
+The time complexity is $O(n \times \log M)$, where $n$ and $M$ are the length and the maximum value of the array $\textit{nums}$, respectively. The space complexity is $O(1)$.
 
 
 
@@ -88,7 +98,7 @@ class Solution:
         def check(mx: int) -> bool:
             return sum((x - 1) // mx for x in nums) <= maxOperations
 
-        return bisect_left(range(1, max(nums)), True, key=check) + 1
+        return bisect_left(range(1, max(nums) + 1), True, key=check) + 1
 ```
 
 #### Java
@@ -96,23 +106,20 @@ class Solution:
 ```java
 class Solution {
     public int minimumSize(int[] nums, int maxOperations) {
-        int left = 1, right = 0;
-        for (int x : nums) {
-            right = Math.max(right, x);
-        }
-        while (left < right) {
-            int mid = (left + right) >> 1;
-            long cnt = 0;
+        int l = 1, r = Arrays.stream(nums).max().getAsInt();
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            long s = 0;
             for (int x : nums) {
-                cnt += (x - 1) / mid;
+                s += (x - 1) / mid;
             }
-            if (cnt <= maxOperations) {
-                right = mid;
+            if (s <= maxOperations) {
+                r = mid;
             } else {
-                left = mid + 1;
+                l = mid + 1;
             }
         }
-        return left;
+        return l;
     }
 }
 ```
@@ -123,20 +130,20 @@ class Solution {
 class Solution {
 public:
     int minimumSize(vector& nums, int maxOperations) {
-        int left = 1, right = *max_element(nums.begin(), nums.end());
-        while (left < right) {
-            int mid = (left + right) >> 1;
-            long long cnt = 0;
+        int l = 1, r = ranges::max(nums);
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            long long s = 0;
             for (int x : nums) {
-                cnt += (x - 1) / mid;
+                s += (x - 1) / mid;
             }
-            if (cnt <= maxOperations) {
-                right = mid;
+            if (s <= maxOperations) {
+                r = mid;
             } else {
-                left = mid + 1;
+                l = mid + 1;
             }
         }
-        return left;
+        return l;
     }
 };
 ```
@@ -148,11 +155,11 @@ func minimumSize(nums []int, maxOperations int) int {
 	r := slices.Max(nums)
 	return 1 + sort.Search(r, func(mx int) bool {
 		mx++
-		cnt := 0
+		s := 0
 		for _, x := range nums {
-			cnt += (x - 1) / mx
+			s += (x - 1) / mx
 		}
-		return cnt <= maxOperations
+		return s <= maxOperations
 	})
 }
 ```
@@ -161,21 +168,45 @@ func minimumSize(nums []int, maxOperations int) int {
 
 ```ts
 function minimumSize(nums: number[], maxOperations: number): number {
-    let left = 1;
-    let right = Math.max(...nums);
-    while (left < right) {
-        const mid = (left + right) >> 1;
-        let cnt = 0;
-        for (const x of nums) {
-            cnt += ~~((x - 1) / mid);
-        }
-        if (cnt <= maxOperations) {
-            right = mid;
+    let [l, r] = [1, Math.max(...nums)];
+    while (l < r) {
+        const mid = (l + r) >> 1;
+        const s = nums.map(x => ((x - 1) / mid) | 0).reduce((a, b) => a + b);
+        if (s <= maxOperations) {
+            r = mid;
         } else {
-            left = mid + 1;
+            l = mid + 1;
+        }
+    }
+    return l;
+}
+```
+
+#### Rust
+
+```rust
+impl Solution {
+    pub fn minimum_size(nums: Vec, max_operations: i32) -> i32 {
+        let mut l = 1;
+        let mut r = *nums.iter().max().unwrap();
+
+        while l < r {
+            let mid = (l + r) / 2;
+            let mut s: i64 = 0;
+
+            for &x in &nums {
+                s += ((x - 1) / mid) as i64;
+            }
+
+            if s <= max_operations as i64 {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
         }
+
+        l
     }
-    return left;
 }
 ```
 
@@ -188,24 +219,43 @@ function minimumSize(nums: number[], maxOperations: number): number {
  * @return {number}
  */
 var minimumSize = function (nums, maxOperations) {
-    let left = 1;
-    let right = Math.max(...nums);
-    while (left < right) {
-        const mid = (left + right) >> 1;
-        let cnt = 0;
-        for (const x of nums) {
-            cnt += ~~((x - 1) / mid);
-        }
-        if (cnt <= maxOperations) {
-            right = mid;
+    let [l, r] = [1, Math.max(...nums)];
+    while (l < r) {
+        const mid = (l + r) >> 1;
+        const s = nums.map(x => ((x - 1) / mid) | 0).reduce((a, b) => a + b);
+        if (s <= maxOperations) {
+            r = mid;
         } else {
-            left = mid + 1;
+            l = mid + 1;
         }
     }
-    return left;
+    return l;
 };
 ```
 
+#### C#
+
+```cs
+public class Solution {
+    public int MinimumSize(int[] nums, int maxOperations) {
+        int l = 1, r = nums.Max();
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            long s = 0;
+            foreach (int x in nums) {
+                s += (x - 1) / mid;
+            }
+            if (s <= maxOperations) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    }
+}
+```
+
 
 
 
diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.cpp b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.cpp
index 6423c68ddfa77..6d5ad2248c7ba 100644
--- a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.cpp	
+++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.cpp	
@@ -1,19 +1,19 @@
 class Solution {
 public:
     int minimumSize(vector& nums, int maxOperations) {
-        int left = 1, right = *max_element(nums.begin(), nums.end());
-        while (left < right) {
-            int mid = (left + right) >> 1;
-            long long cnt = 0;
+        int l = 1, r = ranges::max(nums);
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            long long s = 0;
             for (int x : nums) {
-                cnt += (x - 1) / mid;
+                s += (x - 1) / mid;
             }
-            if (cnt <= maxOperations) {
-                right = mid;
+            if (s <= maxOperations) {
+                r = mid;
             } else {
-                left = mid + 1;
+                l = mid + 1;
             }
         }
-        return left;
+        return l;
     }
-};
\ No newline at end of file
+};
diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.cs b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.cs
new file mode 100644
index 0000000000000..c3f9e3917a1ac
--- /dev/null
+++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.cs	
@@ -0,0 +1,18 @@
+public class Solution {
+    public int MinimumSize(int[] nums, int maxOperations) {
+        int l = 1, r = nums.Max();
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            long s = 0;
+            foreach (int x in nums) {
+                s += (x - 1) / mid;
+            }
+            if (s <= maxOperations) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    }
+}
diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.go b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.go
index f3c1b612aa9d3..61dbad5054590 100644
--- a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.go	
+++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.go	
@@ -2,10 +2,10 @@ func minimumSize(nums []int, maxOperations int) int {
 	r := slices.Max(nums)
 	return 1 + sort.Search(r, func(mx int) bool {
 		mx++
-		cnt := 0
+		s := 0
 		for _, x := range nums {
-			cnt += (x - 1) / mx
+			s += (x - 1) / mx
 		}
-		return cnt <= maxOperations
+		return s <= maxOperations
 	})
-}
\ No newline at end of file
+}
diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.java b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.java
index 48aca93edbf71..c742182e520bc 100644
--- a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.java	
+++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.java	
@@ -1,21 +1,18 @@
 class Solution {
     public int minimumSize(int[] nums, int maxOperations) {
-        int left = 1, right = 0;
-        for (int x : nums) {
-            right = Math.max(right, x);
-        }
-        while (left < right) {
-            int mid = (left + right) >> 1;
-            long cnt = 0;
+        int l = 1, r = Arrays.stream(nums).max().getAsInt();
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            long s = 0;
             for (int x : nums) {
-                cnt += (x - 1) / mid;
+                s += (x - 1) / mid;
             }
-            if (cnt <= maxOperations) {
-                right = mid;
+            if (s <= maxOperations) {
+                r = mid;
             } else {
-                left = mid + 1;
+                l = mid + 1;
             }
         }
-        return left;
+        return l;
     }
-}
\ No newline at end of file
+}
diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.js b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.js
index ece365f4a43d1..54e2c957ac478 100644
--- a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.js	
+++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.js	
@@ -4,19 +4,15 @@
  * @return {number}
  */
 var minimumSize = function (nums, maxOperations) {
-    let left = 1;
-    let right = Math.max(...nums);
-    while (left < right) {
-        const mid = (left + right) >> 1;
-        let cnt = 0;
-        for (const x of nums) {
-            cnt += ~~((x - 1) / mid);
-        }
-        if (cnt <= maxOperations) {
-            right = mid;
+    let [l, r] = [1, Math.max(...nums)];
+    while (l < r) {
+        const mid = (l + r) >> 1;
+        const s = nums.map(x => ((x - 1) / mid) | 0).reduce((a, b) => a + b);
+        if (s <= maxOperations) {
+            r = mid;
         } else {
-            left = mid + 1;
+            l = mid + 1;
         }
     }
-    return left;
+    return l;
 };
diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.py b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.py
index 41c1224361eea..844b7c89e7d96 100644
--- a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.py	
+++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.py	
@@ -3,4 +3,4 @@ def minimumSize(self, nums: List[int], maxOperations: int) -> int:
         def check(mx: int) -> bool:
             return sum((x - 1) // mx for x in nums) <= maxOperations
 
-        return bisect_left(range(1, max(nums)), True, key=check) + 1
+        return bisect_left(range(1, max(nums) + 1), True, key=check) + 1
diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.rs b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.rs
new file mode 100644
index 0000000000000..3bdbf1c191eec
--- /dev/null
+++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.rs	
@@ -0,0 +1,23 @@
+impl Solution {
+    pub fn minimum_size(nums: Vec, max_operations: i32) -> i32 {
+        let mut l = 1;
+        let mut r = *nums.iter().max().unwrap();
+
+        while l < r {
+            let mid = (l + r) / 2;
+            let mut s: i64 = 0;
+
+            for &x in &nums {
+                s += ((x - 1) / mid) as i64;
+            }
+
+            if s <= max_operations as i64 {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+
+        l
+    }
+}
diff --git a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.ts b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.ts
index 63185f0b74848..3313bb7bc541b 100644
--- a/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.ts	
+++ b/solution/1700-1799/1760.Minimum Limit of Balls in a Bag/Solution.ts	
@@ -1,17 +1,13 @@
 function minimumSize(nums: number[], maxOperations: number): number {
-    let left = 1;
-    let right = Math.max(...nums);
-    while (left < right) {
-        const mid = (left + right) >> 1;
-        let cnt = 0;
-        for (const x of nums) {
-            cnt += ~~((x - 1) / mid);
-        }
-        if (cnt <= maxOperations) {
-            right = mid;
+    let [l, r] = [1, Math.max(...nums)];
+    while (l < r) {
+        const mid = (l + r) >> 1;
+        const s = nums.map(x => ((x - 1) / mid) | 0).reduce((a, b) => a + b);
+        if (s <= maxOperations) {
+            r = mid;
         } else {
-            left = mid + 1;
+            l = mid + 1;
         }
     }
-    return left;
+    return l;
 }