Skip to content

Commit 1375467

Browse files
committed
feat: add solutions to lc problem: No.0805
No.0805.Split Array With Same Average
1 parent b6cfc29 commit 1375467

File tree

6 files changed

+424
-2
lines changed

6 files changed

+424
-2
lines changed

solution/0800-0899/0805.Split Array With Same Average/README.md

Lines changed: 175 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,196 @@
4444

4545
<!-- 这里可写通用的实现逻辑 -->
4646

47+
**方法一:折半查找 + 二进制枚举**
48+
49+
根据题目要求,要判断是否可以将数组 `nums` 划分为两个子数组 $A$ 和 $B$,使得两个子数组的平均值相等。
50+
51+
我们记数组 `nums` 的和为 $s$,元素个数为 $n$。子数组 $A$ 的和以及个数分别为 $s_1$ 和 $k$,那么子数组 $B$ 的和为 $s_2 = s - s_1$,个数为 $n - k$,即:
52+
53+
$$
54+
\frac{s_1}{k} = \frac{s_2}{n - k} = \frac{s-s_1}{n-k}
55+
$$
56+
57+
整理可得:
58+
59+
$$
60+
s_1 \times (n-k) = (s-s_1) \times k
61+
$$
62+
63+
化简可得:
64+
65+
$$
66+
\frac{s_1}{k} = \frac{s}{n}
67+
$$
68+
69+
也就是说,要我们找出一个子数组 $A$,使得其平均值等于数组 `nums` 的平均值。我们考虑将数组 `nums` 每个元素都减去数组 `nums` 的平均值,这样问题就转化为了在数组 `nums` 中找出一个子数组,使得其和为 $0$。
70+
71+
但是,数组 `nums` 的平均值可能不是整数,浮点数计算可能存在精度问题,我们不妨将数组 `nums` 中的每个元素都乘以 $n$,即 $nums[i] \leftarrow nums[i] \times n$,上述式子就变成:
72+
73+
$$
74+
\frac{s_1\times n}{k} = s
75+
$$
76+
77+
此时我们将数组 `nums` 中每个元素都减去整数 $s$,题目就转化为:在数组 $nums$ 中找出一个子数组 $A$,使得其和为 $0$。
78+
79+
数组 `nums` 的长度范围为 $[1, 30]$,如果我们使用暴力枚举子数组的方法,时间复杂度为 $O(2^n)$,会超时。我们可以使用折半查找的方法,将时间复杂度降低到 $O(2^{n/2})$。
80+
81+
我们将数组 `nums` 分成左右两部分,那么子数组 $A$ 可能存在三种情况:
82+
83+
1. 子数组 $A$ 完全在数组 `nums` 的左半部分;
84+
2. 子数组 $A$ 完全在数组 `nums` 的右半部分;
85+
3. 子数组 $A$ 一部分在数组 `nums` 的左半部分,一部分在数组 `nums` 的右半部分。
86+
87+
我们可以使用二进制枚举的方法,先枚举左半部分所有子数组的和,如果存在一个子数组和为 $0$,直接返回 `true`,否则我们将其存入哈希表 `vis` 中;然后枚举右半部分所有子数组的和,如果存在一个子数组和为 $0$,直接返回 `true`,否则我们判断此时哈希表 `vis` 中是否存在该和的相反数,如果存在,直接返回 `true`
88+
89+
需要注意的是,我们不能同时全选左半部分和右半部分,因为这样会导致子数组 $B$ 为空,这是不符合题意的。
90+
91+
时间复杂度 $O(n\times 2^{\frac{n}{2}})$,空间复杂度 $O(2^{\frac{n}{2}})$。
92+
4793
<!-- tabs:start -->
4894

4995
### **Python3**
5096

5197
<!-- 这里可写当前语言的特殊实现逻辑 -->
5298

5399
```python
54-
100+
class Solution:
101+
def splitArraySameAverage(self, nums: List[int]) -> bool:
102+
n = len(nums)
103+
if n == 1:
104+
return False
105+
s = sum(nums)
106+
for i, v in enumerate(nums):
107+
nums[i] = v * n - s
108+
m = n >> 1
109+
vis = set()
110+
for i in range(1, 1 << m):
111+
t = sum(v for j, v in enumerate(nums[:m]) if i >> j & 1)
112+
if t == 0:
113+
return True
114+
vis.add(t)
115+
for i in range(1, 1 << (n - m)):
116+
t = sum(v for j, v in enumerate(nums[m:]) if i >> j & 1)
117+
if t == 0 or (i != (1 << (n - m)) - 1 and -t in vis):
118+
return True
119+
return False
55120
```
56121

57122
### **Java**
58123

59124
<!-- 这里可写当前语言的特殊实现逻辑 -->
60125

61126
```java
127+
class Solution {
128+
public boolean splitArraySameAverage(int[] nums) {
129+
int n = nums.length;
130+
if (n == 1) {
131+
return false;
132+
}
133+
int s = Arrays.stream(nums).sum();
134+
for (int i = 0; i < n; ++i) {
135+
nums[i] = nums[i] * n - s;
136+
}
137+
int m = n >> 1;
138+
Set<Integer> vis = new HashSet<>();
139+
for (int i = 1; i < 1 << m; ++i) {
140+
int t = 0;
141+
for (int j = 0; j < m; ++j) {
142+
if (((i >> j) & 1) == 1) {
143+
t += nums[j];
144+
}
145+
}
146+
if (t == 0) {
147+
return true;
148+
}
149+
vis.add(t);
150+
}
151+
for (int i = 1; i < 1 << (n - m); ++i) {
152+
int t = 0;
153+
for (int j = 0; j < (n - m); ++j) {
154+
if (((i >> j) & 1) == 1) {
155+
t += nums[m + j];
156+
}
157+
}
158+
if (t == 0 || (i != (1 << (n - m)) - 1) && vis.contains(-t)) {
159+
return true;
160+
}
161+
}
162+
return false;
163+
}
164+
}
165+
```
166+
167+
### **C++**
168+
169+
```cpp
170+
class Solution {
171+
public:
172+
bool splitArraySameAverage(vector<int>& nums) {
173+
int n = nums.size();
174+
if (n == 1) return false;
175+
int s = accumulate(nums.begin(), nums.end(), 0);
176+
for (int i = 0; i < n; ++i) nums[i] = nums[i] * n - s;
177+
int m = n >> 1;
178+
unordered_set<int> vis;
179+
for (int i = 1; i < 1 << m; ++i) {
180+
int t = 0;
181+
for (int j = 0; j < m; ++j) if (i >> j & 1) t += nums[j];
182+
if (t == 0) return true;
183+
vis.insert(t);
184+
}
185+
for (int i = 1; i < 1 << (n - m); ++i) {
186+
int t = 0;
187+
for (int j = 0; j < (n - m); ++j) if (i >> j & 1) t += nums[m + j];
188+
if (t == 0 || (i != (1 << (n - m)) - 1 && vis.count(-t))) return true;
189+
}
190+
return false;
191+
}
192+
};
193+
```
62194
195+
### **Go**
196+
197+
```go
198+
func splitArraySameAverage(nums []int) bool {
199+
n := len(nums)
200+
if n == 1 {
201+
return false
202+
}
203+
s := 0
204+
for _, v := range nums {
205+
s += v
206+
}
207+
for i, v := range nums {
208+
nums[i] = v*n - s
209+
}
210+
m := n >> 1
211+
vis := map[int]bool{}
212+
for i := 1; i < 1<<m; i++ {
213+
t := 0
214+
for j, v := range nums[:m] {
215+
if (i >> j & 1) == 1 {
216+
t += v
217+
}
218+
}
219+
if t == 0 {
220+
return true
221+
}
222+
vis[t] = true
223+
}
224+
for i := 1; i < 1<<(n-m); i++ {
225+
t := 0
226+
for j, v := range nums[m:] {
227+
if (i >> j & 1) == 1 {
228+
t += v
229+
}
230+
}
231+
if t == 0 || (i != (1<<(n-m))-1 && vis[-t]) {
232+
return true
233+
}
234+
}
235+
return false
236+
}
63237
```
64238

65239
### **...**

solution/0800-0899/0805.Split Array With Same Average/README_EN.md

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,141 @@
4343
### **Python3**
4444

4545
```python
46-
46+
class Solution:
47+
def splitArraySameAverage(self, nums: List[int]) -> bool:
48+
n = len(nums)
49+
if n == 1:
50+
return False
51+
s = sum(nums)
52+
for i, v in enumerate(nums):
53+
nums[i] = v * n - s
54+
m = n >> 1
55+
vis = set()
56+
for i in range(1, 1 << m):
57+
t = sum(v for j, v in enumerate(nums[:m]) if i >> j & 1)
58+
if t == 0:
59+
return True
60+
vis.add(t)
61+
for i in range(1, 1 << (n - m)):
62+
t = sum(v for j, v in enumerate(nums[m:]) if i >> j & 1)
63+
if t == 0 or (i != (1 << (n - m)) - 1 and -t in vis):
64+
return True
65+
return False
4766
```
4867

4968
### **Java**
5069

5170
```java
71+
class Solution {
72+
public boolean splitArraySameAverage(int[] nums) {
73+
int n = nums.length;
74+
if (n == 1) {
75+
return false;
76+
}
77+
int s = Arrays.stream(nums).sum();
78+
for (int i = 0; i < n; ++i) {
79+
nums[i] = nums[i] * n - s;
80+
}
81+
int m = n >> 1;
82+
Set<Integer> vis = new HashSet<>();
83+
for (int i = 1; i < 1 << m; ++i) {
84+
int t = 0;
85+
for (int j = 0; j < m; ++j) {
86+
if (((i >> j) & 1) == 1) {
87+
t += nums[j];
88+
}
89+
}
90+
if (t == 0) {
91+
return true;
92+
}
93+
vis.add(t);
94+
}
95+
for (int i = 1; i < 1 << (n - m); ++i) {
96+
int t = 0;
97+
for (int j = 0; j < (n - m); ++j) {
98+
if (((i >> j) & 1) == 1) {
99+
t += nums[m + j];
100+
}
101+
}
102+
if (t == 0 || (i != (1 << (n - m)) - 1) && vis.contains(-t)) {
103+
return true;
104+
}
105+
}
106+
return false;
107+
}
108+
}
109+
```
110+
111+
### **C++**
112+
113+
```cpp
114+
class Solution {
115+
public:
116+
bool splitArraySameAverage(vector<int>& nums) {
117+
int n = nums.size();
118+
if (n == 1) return false;
119+
int s = accumulate(nums.begin(), nums.end(), 0);
120+
for (int i = 0; i < n; ++i) nums[i] = nums[i] * n - s;
121+
int m = n >> 1;
122+
unordered_set<int> vis;
123+
for (int i = 1; i < 1 << m; ++i) {
124+
int t = 0;
125+
for (int j = 0; j < m; ++j) if (i >> j & 1) t += nums[j];
126+
if (t == 0) return true;
127+
vis.insert(t);
128+
}
129+
for (int i = 1; i < 1 << (n - m); ++i) {
130+
int t = 0;
131+
for (int j = 0; j < (n - m); ++j) if (i >> j & 1) t += nums[m + j];
132+
if (t == 0 || (i != (1 << (n - m)) - 1 && vis.count(-t))) return true;
133+
}
134+
return false;
135+
}
136+
};
137+
```
52138
139+
### **Go**
140+
141+
```go
142+
func splitArraySameAverage(nums []int) bool {
143+
n := len(nums)
144+
if n == 1 {
145+
return false
146+
}
147+
s := 0
148+
for _, v := range nums {
149+
s += v
150+
}
151+
for i, v := range nums {
152+
nums[i] = v*n - s
153+
}
154+
m := n >> 1
155+
vis := map[int]bool{}
156+
for i := 1; i < 1<<m; i++ {
157+
t := 0
158+
for j, v := range nums[:m] {
159+
if (i >> j & 1) == 1 {
160+
t += v
161+
}
162+
}
163+
if t == 0 {
164+
return true
165+
}
166+
vis[t] = true
167+
}
168+
for i := 1; i < 1<<(n-m); i++ {
169+
t := 0
170+
for j, v := range nums[m:] {
171+
if (i >> j & 1) == 1 {
172+
t += v
173+
}
174+
}
175+
if t == 0 || (i != (1<<(n-m))-1 && vis[-t]) {
176+
return true
177+
}
178+
}
179+
return false
180+
}
53181
```
54182

55183
### **...**
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution {
2+
public:
3+
bool splitArraySameAverage(vector<int>& nums) {
4+
int n = nums.size();
5+
if (n == 1) return false;
6+
int s = accumulate(nums.begin(), nums.end(), 0);
7+
for (int i = 0; i < n; ++i) nums[i] = nums[i] * n - s;
8+
int m = n >> 1;
9+
unordered_set<int> vis;
10+
for (int i = 1; i < 1 << m; ++i) {
11+
int t = 0;
12+
for (int j = 0; j < m; ++j) if (i >> j & 1) t += nums[j];
13+
if (t == 0) return true;
14+
vis.insert(t);
15+
}
16+
for (int i = 1; i < 1 << (n - m); ++i) {
17+
int t = 0;
18+
for (int j = 0; j < (n - m); ++j) if (i >> j & 1) t += nums[m + j];
19+
if (t == 0 || (i != (1 << (n - m)) - 1 && vis.count(-t))) return true;
20+
}
21+
return false;
22+
}
23+
};

0 commit comments

Comments
 (0)