Skip to content

Commit ec9a531

Browse files
committed
feat: add solutions to lc problems: No.2357,2358
* No.2357.Make Array Zero by Subtracting Equal Amounts * No.2358.Maximum Number of Groups Entering a Competition
1 parent aef9e1c commit ec9a531

File tree

13 files changed

+208
-208
lines changed

13 files changed

+208
-208
lines changed

solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README.md

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@
4848

4949
<!-- 这里可写通用的实现逻辑 -->
5050

51-
**方法一:哈希表去重**
51+
**方法一:哈希表或数组**
5252

53-
求去重后的非零元素个数
53+
我们观察到,每一次操作,都可以把数组 `nums` 中相同且非零的元素减少到 $0$,因此,我们只需要统计数组 `nums` 中有多少个不同的非零元素,即为最少操作数。统计不同的非零元素,可以使用哈希表或数组来实现
5454

55-
时间复杂度 $O(n)$。
55+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组长度
5656

5757
<!-- tabs:start -->
5858

@@ -63,8 +63,7 @@
6363
```python
6464
class Solution:
6565
def minimumOperations(self, nums: List[int]) -> int:
66-
s = {v for v in nums if v}
67-
return len(s)
66+
return len({x for x in nums if x})
6867
```
6968

7069
### **Java**
@@ -74,13 +73,16 @@ class Solution:
7473
```java
7574
class Solution {
7675
public int minimumOperations(int[] nums) {
77-
Set<Integer> s = new HashSet<>();
78-
for (int v : nums) {
79-
if (v > 0) {
80-
s.add(v);
76+
boolean[] s = new boolean[101];
77+
s[0] = true;
78+
int ans = 0;
79+
for (int x : nums) {
80+
if (!s[x]) {
81+
++ans;
82+
s[x] = true;
8183
}
8284
}
83-
return s.size();
85+
return ans;
8486
}
8587
}
8688
```
@@ -91,25 +93,32 @@ class Solution {
9193
class Solution {
9294
public:
9395
int minimumOperations(vector<int>& nums) {
94-
unordered_set<int> s;
95-
for (int v : nums)
96-
if (v) s.insert(v);
97-
return s.size();
96+
bool s[101]{};
97+
s[0] = true;
98+
int ans = 0;
99+
for (int& x : nums) {
100+
if (!s[x]) {
101+
++ans;
102+
s[x] = true;
103+
}
104+
}
105+
return ans;
98106
}
99107
};
100108
```
101109
102110
### **Go**
103111
104112
```go
105-
func minimumOperations(nums []int) int {
106-
s := map[int]bool{}
107-
for _, v := range nums {
108-
if v > 0 {
109-
s[v] = true
113+
func minimumOperations(nums []int) (ans int) {
114+
s := [101]bool{true}
115+
for _, x := range nums {
116+
if !s[x] {
117+
s[x] = true
118+
ans++
110119
}
111120
}
112-
return len(s)
121+
return
113122
}
114123
```
115124

solution/2300-2399/2357.Make Array Zero by Subtracting Equal Amounts/README_EN.md

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,24 @@ In the third operation, choose x = 2. Now, nums = [0,0,0,0,0].
5050
```python
5151
class Solution:
5252
def minimumOperations(self, nums: List[int]) -> int:
53-
s = {v for v in nums if v}
54-
return len(s)
53+
return len({x for x in nums if x})
5554
```
5655

5756
### **Java**
5857

5958
```java
6059
class Solution {
6160
public int minimumOperations(int[] nums) {
62-
Set<Integer> s = new HashSet<>();
63-
for (int v : nums) {
64-
if (v > 0) {
65-
s.add(v);
61+
boolean[] s = new boolean[101];
62+
s[0] = true;
63+
int ans = 0;
64+
for (int x : nums) {
65+
if (!s[x]) {
66+
++ans;
67+
s[x] = true;
6668
}
6769
}
68-
return s.size();
70+
return ans;
6971
}
7072
}
7173
```
@@ -76,25 +78,32 @@ class Solution {
7678
class Solution {
7779
public:
7880
int minimumOperations(vector<int>& nums) {
79-
unordered_set<int> s;
80-
for (int v : nums)
81-
if (v) s.insert(v);
82-
return s.size();
81+
bool s[101]{};
82+
s[0] = true;
83+
int ans = 0;
84+
for (int& x : nums) {
85+
if (!s[x]) {
86+
++ans;
87+
s[x] = true;
88+
}
89+
}
90+
return ans;
8391
}
8492
};
8593
```
8694
8795
### **Go**
8896
8997
```go
90-
func minimumOperations(nums []int) int {
91-
s := map[int]bool{}
92-
for _, v := range nums {
93-
if v > 0 {
94-
s[v] = true
98+
func minimumOperations(nums []int) (ans int) {
99+
s := [101]bool{true}
100+
for _, x := range nums {
101+
if !s[x] {
102+
s[x] = true
103+
ans++
95104
}
96105
}
97-
return len(s)
106+
return
98107
}
99108
```
100109

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
class Solution {
22
public:
33
int minimumOperations(vector<int>& nums) {
4-
unordered_set<int> s;
5-
for (int v : nums)
6-
if (v) s.insert(v);
7-
return s.size();
4+
bool s[101]{};
5+
s[0] = true;
6+
int ans = 0;
7+
for (int& x : nums) {
8+
if (!s[x]) {
9+
++ans;
10+
s[x] = true;
11+
}
12+
}
13+
return ans;
814
}
915
};
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
func minimumOperations(nums []int) int {
2-
s := map[int]bool{}
3-
for _, v := range nums {
4-
if v > 0 {
5-
s[v] = true
1+
func minimumOperations(nums []int) (ans int) {
2+
s := [101]bool{true}
3+
for _, x := range nums {
4+
if !s[x] {
5+
s[x] = true
6+
ans++
67
}
78
}
8-
return len(s)
9+
return
910
}
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
class Solution {
22
public int minimumOperations(int[] nums) {
3-
Set<Integer> s = new HashSet<>();
4-
for (int v : nums) {
5-
if (v > 0) {
6-
s.add(v);
3+
boolean[] s = new boolean[101];
4+
s[0] = true;
5+
int ans = 0;
6+
for (int x : nums) {
7+
if (!s[x]) {
8+
++ans;
9+
s[x] = true;
710
}
811
}
9-
return s.size();
12+
return ans;
1013
}
1114
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
class Solution:
22
def minimumOperations(self, nums: List[int]) -> int:
3-
s = {v for v in nums if v}
4-
return len(s)
3+
return len({x for x in nums if x})

solution/2300-2399/2358.Maximum Number of Groups Entering a Competition/README.md

Lines changed: 49 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,17 @@
4848

4949
<!-- 这里可写通用的实现逻辑 -->
5050

51-
**方法一:排序**
51+
**方法一:贪心 + 二分查找**
5252

53-
时间复杂度 $O(nlogn)$。
53+
我们观察题目中的条件,第 $i$ 组的学生人数要小于第 $i+1$ 组的学生人数,且第 $i$ 组的学生总成绩要小于第 $i+1$ 组的学生总成绩,我们只需要将学生按照成绩从小到大排序,然后每一组依次分配 $1$, $2$, ..., $k$ 个学生即可。如果最后一组的学生人数不足 $k$ 个,那么我们可以将这些学生分配到前面的最后一组中。
54+
55+
因此,我们要找到最大的 $k$,使得 $\frac{(1 + k) \times k}{2} \leq n$,其中 $n$ 为学生的总人数。我们可以使用二分查找来求解。
56+
57+
我们定义二分查找的左边界为 $l = 1$,右边界为 $r = n$,每一次二分查找的中点为 $mid = \lfloor \frac{l + r + 1}{2} \rfloor$,如果 $(1 + mid) \times mid \gt 2 \times n$,则说明 $mid$ 太大,我们需要将右边界缩小至 $mid - 1$,否则我们需要将左边界增大至 $mid$。
58+
59+
最后,我们将 $l$ 作为答案返回即可。
60+
61+
时间复杂度 $O(\log n)$,空间复杂度 $O(1)$。其中 $n$ 为学生的总人数。
5462

5563
<!-- tabs:start -->
5664

@@ -61,18 +69,8 @@
6169
```python
6270
class Solution:
6371
def maximumGroups(self, grades: List[int]) -> int:
64-
grades.sort()
65-
ans = 1
66-
prev = [1, grades[0]]
67-
curr = [0, 0]
68-
for v in grades[1:]:
69-
curr[0] += 1
70-
curr[1] += v
71-
if prev[0] < curr[0] and prev[1] < curr[1]:
72-
prev = curr
73-
curr = [0, 0]
74-
ans += 1
75-
return ans
72+
n = len(grades)
73+
return bisect_right(range(n + 1), n * 2, key=lambda x: x * x + x) - 1
7674
```
7775

7876
### **Java**
@@ -82,20 +80,17 @@ class Solution:
8280
```java
8381
class Solution {
8482
public int maximumGroups(int[] grades) {
85-
Arrays.sort(grades);
86-
int ans = 1;
87-
int[] prev = new int[] {1, grades[0]};
88-
int[] curr = new int[] {0, 0};
89-
for (int i = 1; i < grades.length; ++i) {
90-
curr[0]++;
91-
curr[1] += grades[i];
92-
if (prev[0] < curr[0] && prev[1] < curr[1]) {
93-
prev = curr;
94-
curr = new int[] {0, 0};
95-
++ans;
83+
int n = grades.length;
84+
int l = 0, r = n;
85+
while (l < r) {
86+
int mid = (l + r + 1) >> 1;
87+
if (1L * mid * mid + mid > n * 2L) {
88+
r = mid - 1;
89+
} else {
90+
l = mid;
9691
}
9792
}
98-
return ans;
93+
return l;
9994
}
10095
}
10196
```
@@ -106,20 +101,17 @@ class Solution {
106101
class Solution {
107102
public:
108103
int maximumGroups(vector<int>& grades) {
109-
sort(grades.begin(), grades.end());
110-
int ans = 1;
111-
vector<int> prev = {1, grades[0]};
112-
vector<int> curr = {0, 0};
113-
for (int i = 1; i < grades.size(); ++i) {
114-
curr[0]++;
115-
curr[1] += grades[i];
116-
if (prev[0] < curr[0] && prev[1] < curr[1]) {
117-
prev = curr;
118-
curr = {0, 0};
119-
++ans;
104+
int n = grades.size();
105+
int l = 0, r = n;
106+
while (l < r) {
107+
int mid = (l + r + 1) >> 1;
108+
if (1LL * mid * mid + mid > n * 2LL) {
109+
r = mid - 1;
110+
} else {
111+
l = mid;
120112
}
121113
}
122-
return ans;
114+
return l;
123115
}
124116
};
125117
```
@@ -128,27 +120,31 @@ public:
128120
129121
```go
130122
func maximumGroups(grades []int) int {
131-
sort.Ints(grades)
132-
ans := 1
133-
prev := []int{1, grades[0]}
134-
curr := []int{0, 0}
135-
for _, v := range grades[1:] {
136-
curr[0]++
137-
curr[1] += v
138-
if prev[0] < curr[0] && prev[1] < curr[1] {
139-
prev = curr
140-
curr = []int{0, 0}
141-
ans++
142-
}
143-
}
144-
return ans
123+
n := len(grades)
124+
return sort.Search(n, func(k int) bool {
125+
k++
126+
return k*k+k > n*2
127+
})
145128
}
146129
```
147130

148131
### **TypeScript**
149132

150133
```ts
151-
134+
function maximumGroups(grades: number[]): number {
135+
const n = grades.length;
136+
let l = 1;
137+
let r = n;
138+
while (l < r) {
139+
const mid = (l + r + 1) >> 1;
140+
if (mid * mid + mid > n * 2) {
141+
r = mid - 1;
142+
} else {
143+
l = mid;
144+
}
145+
}
146+
return l;
147+
}
152148
```
153149

154150
### **...**

0 commit comments

Comments
 (0)