14
14
15
15
<ul >
16
16
<li>数组的中位数是按 <strong>递增</strong> 顺序排列后位于 <strong>中间</strong> 的那个元素,如果数组长度为偶数,则中位数是位于中间靠 <strong>左</strong> 的那个元素。
17
-
18
17
<ul>
19
18
<li>例如,<code>[2,3,1,4]</code> 的中位数是 <code>2</code> ,<code>[8,4,3,5,1]</code> 的中位数是 <code>4</code> 。</li>
20
19
</ul>
21
20
</li>
22
21
<li>子数组是数组中的一个连续部分。</li>
23
-
24
22
</ul >
25
23
26
24
<p >  ; </p >
56
54
57
55
<!-- 这里可写通用的实现逻辑 -->
58
56
59
- ** 方法一:中心扩展**
57
+ ** 方法一:遍历 + 计数**
58
+
59
+ 我们先找到中位数 $k$ 在数组中的位置 $i$,然后从 $i$ 开始向两边遍历,统计中位数为 $k$ 的子数组的数目。
60
+
61
+ 定义一个答案变量 $ans$,表示中位数为 $k$ 的子数组的数目。初始时 $ans = 1$,表示当前有一个长度为 $1$ 的子数组,其中位数为 $k$。另外,定义一个计数器 $cnt$,用于统计当前数组中,「比 $k$ 大的元素的个数」与「比 $k$ 小的元素的个数」的差值。
60
62
61
- 我们先找到数字 $ k$ 所在的位置 $i$,然后从 $i$ 向两边扩展,统计以 $i$ 为中心的子数组个数 。
63
+ 接下来,从 $i + 1$ 开始向右遍历,我们维护一个变量 $x$,表示当前右侧子数组中「比 $ k$ 大的元素的个数」与「比 $k$ 小的元素的个数」的差值。如果 $x \in [ 0, 1 ] $,则当前右侧子数组的中位数为 $k$,答案变量 $ans$ 自增 $1$。然后,我们将 $x$ 的值加入计数器 $cnt$ 中 。
62
64
63
- 扩展的过程中维护两个变量 $mi$ 和 $mx$,分别表示比 $k$ 小的数字个数和比 $k$ 大的数字个数 。
65
+ 同理,从 $i - 1$ 开始向左遍历,同样维护一个变量 $x$,表示当前左侧子数组中「比 $k$ 大的元素的个数」与「比 $k$ 小的元素的个数」的差值。如果 $x \in [ 0, 1 ] $,则当前左侧子数组的中位数为 $k$,答案变量 $ans$ 自增 $1$。如果 $-x$ 或 $-x + 1$ 也在计数器中,说明当前存在跨越 $i$ 左右两侧的子数组,其中位数为 $k$,答案变量 $ans$ 增加计数器中对应的值,即 $ans += cnt [ -x ] + cnt [ -x + 1 ] $ 。
64
66
65
- 先从 $i+1$ 向右扩展,若出现 $0 \leq mx-mi \leq 1$,此时右侧数组的中位数为 $k$,答案加 $1$。然后我们将 $mx-mi$ 的出现次数存放在数组或哈希表中,以便后续查询 。
67
+ 最后,返回答案变量 $ans$ 即可 。
66
68
67
- 接着从 $i-1$ 向左扩展,若出现 $0 \leq mx-mi \leq 1$,此时左侧数组的中位数为 $k$,答案加 $1$。然后我们查询数组或哈希表中 $mi-mx$ 以及 $mi-mx+1$ 的出现次数,将其加到答案中 。
69
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度 。
68
70
69
- 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组长度 。
71
+ > 在编码上,我们可以直接开一个长度为 $2 \times n + 1$ 的数组,用于统计当前数组中,比 $k$ 大的元素的个数与比 $k$ 小的元素的个数的差值,每一次我们将差值加上 $n$,即可将差值的范围从 $ [ -n, n ] $ 转换为 $ [ 0, 2n ] $ 。
70
72
71
73
<!-- tabs:start -->
72
74
77
79
``` python
78
80
class Solution :
79
81
def countSubarrays (self , nums : List[int ], k : int ) -> int :
80
- i = next (i for i, v in enumerate ( nums) if v == k)
81
- n = len (nums )
82
+ i = nums.index( k)
83
+ cnt = Counter( )
82
84
ans = 1
83
- d = defaultdict(int )
84
- mi = mx = 0
85
- for j in range (i + 1 , n):
86
- if nums[j] < k:
87
- mi += 1
88
- else :
89
- mx += 1
90
- if 0 <= mx - mi <= 1 :
91
- ans += 1
92
- d[mx - mi] += 1
93
- mi = mx = 0
85
+ x = 0
86
+ for v in nums[i + 1 :]:
87
+ x += 1 if v > k else - 1
88
+ ans += 0 <= x <= 1
89
+ cnt[x] += 1
90
+ x = 0
94
91
for j in range (i - 1 , - 1 , - 1 ):
95
- if nums[j] < k:
96
- mi += 1
97
- else :
98
- mx += 1
99
- if 0 <= mx - mi <= 1 :
100
- ans += 1
101
- ans += d[mi - mx] + d[mi - mx + 1 ]
92
+ x += 1 if nums[j] > k else - 1
93
+ ans += 0 <= x <= 1
94
+ ans += cnt[- x] + cnt[- x + 1 ]
102
95
return ans
103
96
```
104
97
@@ -111,38 +104,24 @@ class Solution {
111
104
public int countSubarrays (int [] nums , int k ) {
112
105
int n = nums. length;
113
106
int i = 0 ;
114
- for (int j = 0 ; j < n; ++ j) {
115
- if (nums[j] == k) {
116
- i = j;
117
- break ;
118
- }
119
- }
107
+ for (; nums[i] != k; ++ i) {}
108
+ int [] cnt = new int [n << 1 | 1 ];
120
109
int ans = 1 ;
121
- int [] d = new int [n << 1 | 1 ];
122
- int mi = 0 , mx = 0 ;
110
+ int x = 0 ;
123
111
for (int j = i + 1 ; j < n; ++ j) {
124
- if (nums[j] < k) {
125
- ++ mi;
126
- } else {
127
- ++ mx;
128
- }
129
- if (mx - mi >= 0 && mx - mi <= 1 ) {
112
+ x += nums[j] > k ? 1 : - 1 ;
113
+ if (x >= 0 && x <= 1 ) {
130
114
++ ans;
131
115
}
132
- ++ d[mx - mi + n];
116
+ ++ cnt[x + n];
133
117
}
134
- mi = 0 ;
135
- mx = 0 ;
118
+ x = 0 ;
136
119
for (int j = i - 1 ; j >= 0 ; -- j) {
137
- if (nums[j] < k) {
138
- ++ mi;
139
- } else {
140
- ++ mx;
141
- }
142
- if (mx - mi >= 0 && mx - mi <= 1 ) {
120
+ x += nums[j] > k ? 1 : - 1 ;
121
+ if (x >= 0 && x <= 1 ) {
143
122
++ ans;
144
123
}
145
- ans += d[mi - mx + n] + d[mi - mx + 1 + n];
124
+ ans += cnt[ - x + n] + cnt[ - x + 1 + n];
146
125
}
147
126
return ans;
148
127
}
@@ -156,29 +135,25 @@ class Solution {
156
135
public:
157
136
int countSubarrays(vector<int >& nums, int k) {
158
137
int n = nums.size();
159
- int i = 0;
160
- for (int j = 0; j < n; ++j) {
161
- if (nums[ j] == k) {
162
- i = j;
163
- break;
164
- }
165
- }
138
+ int i = find(nums.begin(), nums.end(), k) - nums.begin();
139
+ int cnt[ n << 1 | 1] ;
140
+ memset(cnt, 0, sizeof(cnt));
166
141
int ans = 1;
167
- int d[ n << 1 | 1] ;
168
- memset(d, 0, sizeof d);
169
- int mi = 0, mx = 0;
142
+ int x = 0;
170
143
for (int j = i + 1; j < n; ++j) {
171
- if (nums[ j] < k) ++mi;
172
- else ++mx;
173
- if (mx - mi >= 0 && mx - mi <= 1) ++ans;
174
- ++d[ mx - mi + n] ;
144
+ x += nums[ j] > k ? 1 : -1;
145
+ if (x >= 0 && x <= 1) {
146
+ ++ans;
147
+ }
148
+ ++cnt[ x + n] ;
175
149
}
176
- mi = 0, mx = 0;
150
+ x = 0;
177
151
for (int j = i - 1; ~ j; --j) {
178
- if (nums[ j] < k) ++mi;
179
- else ++mx;
180
- if (mx - mi >= 0 && mx - mi <= 1) ++ans;
181
- ans += d[ mi - mx + n] + d[ mi - mx + n + 1] ;
152
+ x += nums[ j] > k ? 1 : -1;
153
+ if (x >= 0 && x <= 1) {
154
+ ++ans;
155
+ }
156
+ ans += cnt[ -x + n] + cnt[ -x + 1 + n] ;
182
157
}
183
158
return ans;
184
159
}
@@ -189,41 +164,61 @@ public:
189
164
190
165
```go
191
166
func countSubarrays(nums []int, k int) int {
192
- n := len(nums)
193
- var i int
194
- for j, v := range nums {
195
- if v == k {
196
- i = j
197
- break
198
- }
199
- }
200
- ans := 1
201
- d := make([]int, n<<1|1)
202
- mi, mx := 0, 0
203
- for j := i + 1; j < n; j++ {
204
- if nums[j] < k {
205
- mi++
206
- } else {
207
- mx++
208
- }
209
- if mx-mi >= 0 && mx-mi <= 1 {
210
- ans++
211
- }
212
- d[mx-mi+n]++
213
- }
214
- mi, mx = 0, 0
215
- for j := i - 1; j >= 0; j-- {
216
- if nums[j] < k {
217
- mi++
218
- } else {
219
- mx++
220
- }
221
- if mx-mi >= 0 && mx-mi <= 1 {
222
- ans++
223
- }
224
- ans += d[mi-mx+n] + d[mi-mx+n+1]
225
- }
226
- return ans
167
+ i, n := 0, len(nums)
168
+ for nums[i] != k {
169
+ i++
170
+ }
171
+ ans := 1
172
+ cnt := make([]int, n << 1 | 1)
173
+ x := 0
174
+ for j := i + 1; j < n; j++ {
175
+ if nums[j] > k {
176
+ x++
177
+ } else {
178
+ x--
179
+ }
180
+ if x >= 0 && x <= 1 {
181
+ ans++
182
+ }
183
+ cnt[x + n]++
184
+ }
185
+ x = 0
186
+ for j := i - 1; j >= 0; j-- {
187
+ if nums[j] > k {
188
+ x++
189
+ } else {
190
+ x--
191
+ }
192
+ if x >= 0 && x <= 1 {
193
+ ans++
194
+ }
195
+ ans += cnt[-x + n] + cnt[-x + 1 + n]
196
+ }
197
+ return ans
198
+ }
199
+ ```
200
+
201
+ ### ** TypeScript**
202
+
203
+ ``` ts
204
+ function countSubarrays(nums : number [], k : number ): number {
205
+ const i = nums .indexOf (k );
206
+ const n = nums .length ;
207
+ const cnt = new Array ((n << 1 ) | 1 ).fill (0 );
208
+ let ans = 1 ;
209
+ let x = 0 ;
210
+ for (let j = i + 1 ; j < n ; ++ j ) {
211
+ x += nums [j ] > k ? 1 : - 1 ;
212
+ ans += x >= 0 && x <= 1 ? 1 : 0 ;
213
+ ++ cnt [x + n ];
214
+ }
215
+ x = 0 ;
216
+ for (let j = i - 1 ; ~ j ; -- j ) {
217
+ x += nums [j ] > k ? 1 : - 1 ;
218
+ ans += x >= 0 && x <= 1 ? 1 : 0 ;
219
+ ans += cnt [- x + n ] + cnt [- x + 1 + n ];
220
+ }
221
+ return ans ;
227
222
}
228
223
```
229
224
0 commit comments