Skip to content

Commit e2dc306

Browse files
authoredJul 2, 2023
feat: add solutions to lc problem: No.0004 (#1125)
No.0004.Median of Two Sorted Arrays
1 parent 1f5eff4 commit e2dc306

File tree

9 files changed

+478
-373
lines changed

9 files changed

+478
-373
lines changed
 

‎solution/0000-0099/0004.Median of Two Sorted Arrays/README.md

+166-58
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,22 @@
4949

5050
**方法一:分治**
5151

52-
本题限制了时间复杂度为 $O(\log (m+n))$,看到这个时间复杂度,自然而然的想到了应该使用二分查找法来求解。那么回顾一下中位数的定义,如果某个有序数组长度是奇数,那么其中位数就是最中间那个,如果是偶数,那么就是最中间两个数字的平均值。这里对于两个有序数组也是一样的,假设两个有序数组的长度分别为 $m$ 和 $n$,由于两个数组长度之和 $m+n$ 的奇偶不确定,因此需要分情况来讨论,对于奇数的情况,直接找到最中间的数即可,偶数的话需要求最中间两个数的平均值。为了简化代码,不分情况讨论,我们使用一个小 trick,我们分别找第 $\frac{m+n+1}{2}$ 和 $\frac{m+n+2}{2}$ 个,然后求其平均值即可,这对奇偶数均适用。假如 $m+n$ 为奇数的话,那么其实 $\frac{m+n+1}{2}$ 和 $\frac{m+n+2}{2}$ 的值相等,相当于两个相同的数字相加再除以 2,还是其本身
52+
题目要求算法的时间复杂度为 $O(\log (m + n))$,因此不能直接遍历两个数组,而是需要使用二分查找的方法
5353

54-
这里我们需要定义一个函数来在两个有序数组中找到第 $k$ 个元素,下面重点来看如何实现找到第 $k$ 个元素
54+
如果 $m + n$ 是奇数,那么中位数就是第 $\left\lfloor\frac{m + n + 1}{2}\right\rfloor$ 个数;如果 $m + n$ 是偶数,那么中位数就是第 $\left\lfloor\frac{m + n + 1}{2}\right\rfloor$ 和第 $\left\lfloor\frac{m + n + 2}{2}\right\rfloor$ 个数的平均数。实际上,我们可以统一为求第 $\left\lfloor\frac{m + n + 1}{2}\right\rfloor$ 个数和第 $\left\lfloor\frac{m + n + 2}{2}\right\rfloor$ 个数的平均数
5555

56-
首先,为了避免产生新的数组从而增加时间复杂度,我们使用两个变量 $i$ 和 $j$ 分别来标记数组 `nums1``nums2` 的起始位置。然后来处理一些边界问题,比如当某一个数组的起始位置大于等于其数组长度时,说明其所有数字均已经被淘汰了,相当于一个空数组了,那么实际上就变成了在另一个数组中找数字,直接就可以找出来了。还有就是如果 $k=1$ 的话,那么我们只要比较 `nums1``nums2` 的起始位置 $i$ 和 $j$ 上的数字就可以了
56+
因此,我们可以设计一个函数 $f(i, j, k)$,表示在数组 $nums1$ 的区间 $[i, m)$ 和数组 $nums2$ 的区间 $[j, n)$ 中,求第 $k$ 小的数。那么中位数就是 $f(0, 0, \left\lfloor\frac{m + n + 1}{2}\right\rfloor)$ 和 $f(0, 0, \left\lfloor\frac{m + n + 2}{2}\right\rfloor)$ 的平均数
5757

58-
难点就在于一般的情况怎么处理?因为我们需要在两个有序数组中找到第 $k$ 个元素,为了加快搜索的速度,我们要使用二分法,对 $k$ 二分,意思是我们需要分别在 `nums1` 和 `nums2` 中查找第 $\left \lfloor \frac{k}{2} \right \rfloor$ 个元素,注意这里由于两个数组的长度不定,所以有可能某个数组没有第 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字,所以我们需要先检查一下,数组中到底存不存在第 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字,如果存在就取出来,否则就赋值上一个整型最大值。如果某个数组没有第 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字,那么我们就淘汰另一个数字的前 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字即可。有没有可能两个数组都不存在第 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字呢,这道题里是不可能的,因为我们的 $k$ 不是任意给的,而是给的 $m+n$ 的中间值,所以必定至少会有一个数组是存在第 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字的。
58+
函数 $f(i, j, k)$ 的实现思路如下:
5959

60-
最后是二分法的核心,比较这两个数组的第 $\left \lfloor \frac{k}{2} \right \rfloor$ 小的数字 `midVal1``midVal2` 的大小,如果第一个数组的第 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字小的话,那么说明我们要找的数字肯定不在 `nums1` 中的前 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字,所以我们可以将其淘汰,将 `nums1` 的起始位置向后移动 $\left \lfloor \frac{k}{2} \right \rfloor$ 个,并且此时的 $k$ 也自减去 $\left \lfloor \frac{k}{2} \right \rfloor$,调用递归。反之,我们淘汰 `nums2` 中的前 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字,并将 `nums2` 的起始位置向后移动 $\left \lfloor \frac{k}{2} \right \rfloor$ 个,并且此时的 $k$ 也自减去 $\left \lfloor \frac{k}{2} \right \rfloor$,调用递归即可。
60+
- 如果 $i \geq m$,说明数组 $nums1$ 的区间 $[i, m)$ 为空,因此直接返回 $nums2[j + k - 1]$;
61+
- 如果 $j \geq n$,说明数组 $nums2$ 的区间 $[j, n)$ 为空,因此直接返回 $nums1[i + k - 1]$;
62+
- 如果 $k = 1$,说明要找第一个数,因此只需要返回 $nums1[i]$ 和 $nums2[j]$ 中的最小值;
63+
- 否则,我们分别在两个数组中查找第 $\left\lfloor\frac{k}{2}\right\rfloor$ 个数,设为 $x$ 和 $y$。(注意,如果某个数组不存在第 $\left\lfloor\frac{k}{2}\right\rfloor$ 个数,那么我们将第 $\left\lfloor\frac{k}{2}\right\rfloor$ 个数视为 $+\infty$。)比较 $x$ 和 $y$ 的大小:
64+
- 如果 $x \leq y$,则说明数组 $nums1$ 的第 $\left\lfloor\frac{k}{2}\right\rfloor$ 个数不可能是第 $k$ 小的数,因此我们可以排除数组 $nums1$ 的区间 $[i, i + \left\lfloor\frac{k}{2}\right\rfloor)$,递归调用 $f(i + \left\lfloor\frac{k}{2}\right\rfloor, j, k - \left\lfloor\frac{k}{2}\right\rfloor)$。
65+
- 如果 $x > y$,则说明数组 $nums2$ 的第 $\left\lfloor\frac{k}{2}\right\rfloor$ 个数不可能是第 $k$ 小的数,因此我们可以排除数组 $nums2$ 的区间 $[j, j + \left\lfloor\frac{k}{2}\right\rfloor)$,递归调用 $f(i, j + \left\lfloor\frac{k}{2}\right\rfloor, k - \left\lfloor\frac{k}{2}\right\rfloor)$。
6166

62-
> 实际是比较两个数组中的第 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字哪一个可能到达最后合并后排序数组中的第 $k$ 个元素的位置,其中小的那个数字注定不可能到达,所以可以直接将小的元素对应的数组的前 $\left \lfloor \frac{k}{2} \right \rfloor$ 个数字淘汰。
63-
64-
时间复杂度 $O(\log (m+n))$,其中 $m$ 和 $n$ 是两个数组的长度。
67+
时间复杂度 $O(\log(m + n))$,空间复杂度 $O(\log(m + n))$。其中 $m$ 和 $n$ 分别是数组 $nums1$ 和 $nums2$ 的长度。
6568

6669
<!-- tabs:start -->
6770

@@ -72,22 +75,22 @@
7275
```python
7376
class Solution:
7477
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
75-
def findKth(i, j, k):
78+
def f(i: int, j: int, k: int) -> int:
7679
if i >= m:
7780
return nums2[j + k - 1]
7881
if j >= n:
7982
return nums1[i + k - 1]
8083
if k == 1:
8184
return min(nums1[i], nums2[j])
82-
midVal1 = nums1[i + k // 2 - 1] if i + k // 2 - 1 < m else inf
83-
midVal2 = nums2[j + k // 2 - 1] if j + k // 2 - 1 < n else inf
84-
if midVal1 < midVal2:
85-
return findKth(i + k // 2, j, k - k // 2)
86-
return findKth(i, j + k // 2, k - k // 2)
85+
p = k // 2
86+
x = nums1[i + p - 1] if i + p - 1 < m else inf
87+
y = nums2[j + p - 1] if j + p - 1 < n else inf
88+
return f(i + p, j, k - p) if x < y else f(i, j + p, k - p)
8789

8890
m, n = len(nums1), len(nums2)
89-
left, right = (m + n + 1) // 2, (m + n + 2) // 2
90-
return (findKth(0, 0, left) + findKth(0, 0, right)) / 2
91+
a = f(0, 0, (m + n + 1) // 2)
92+
b = f(0, 0, (m + n + 2) // 2)
93+
return (a + b) / 2
9194
```
9295

9396
### **Java**
@@ -96,30 +99,35 @@ class Solution:
9699

97100
```java
98101
class Solution {
102+
private int m;
103+
private int n;
104+
private int[] nums1;
105+
private int[] nums2;
106+
99107
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
100-
int m = nums1.length;
101-
int n = nums2.length;
102-
int left = (m + n + 1) / 2;
103-
int right = (m + n + 2) / 2;
104-
return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
108+
m = nums1.length;
109+
n = nums2.length;
110+
this.nums1 = nums1;
111+
this.nums2 = nums2;
112+
int a = f(0, 0, (m + n + 1) / 2);
113+
int b = f(0, 0, (m + n + 2) / 2);
114+
return (a + b) / 2.0;
105115
}
106116

107-
private int findKth(int[] nums1, int i, int[] nums2, int j, int k) {
108-
if (i >= nums1.length) {
117+
private int f(int i, int j, int k) {
118+
if (i >= m) {
109119
return nums2[j + k - 1];
110120
}
111-
if (j >= nums2.length) {
121+
if (j >= n) {
112122
return nums1[i + k - 1];
113123
}
114124
if (k == 1) {
115125
return Math.min(nums1[i], nums2[j]);
116126
}
117-
int midVal1 = (i + k / 2 - 1 < nums1.length) ? nums1[i + k / 2 - 1] : Integer.MAX_VALUE;
118-
int midVal2 = (j + k / 2 - 1 < nums2.length) ? nums2[j + k / 2 - 1] : Integer.MAX_VALUE;
119-
if (midVal1 < midVal2) {
120-
return findKth(nums1, i + k / 2, nums2, j, k - k / 2);
121-
}
122-
return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
127+
int p = k / 2;
128+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
129+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
130+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
123131
}
124132
}
125133
```
@@ -130,21 +138,25 @@ class Solution {
130138
class Solution {
131139
public:
132140
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
133-
int m = nums1.size();
134-
int n = nums2.size();
135-
int left = (m + n + 1) / 2;
136-
int right = (m + n + 2) / 2;
137-
return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
138-
}
139-
140-
int findKth(vector<int>& nums1, int i, vector<int>& nums2, int j, int k) {
141-
if (i >= nums1.size()) return nums2[j + k - 1];
142-
if (j >= nums2.size()) return nums1[i + k - 1];
143-
if (k == 1) return min(nums1[i], nums2[j]);
144-
int midVal1 = i + k / 2 - 1 < nums1.size() ? nums1[i + k / 2 - 1] : INT_MAX;
145-
int midVal2 = j + k / 2 - 1 < nums2.size() ? nums2[j + k / 2 - 1] : INT_MAX;
146-
if (midVal1 < midVal2) return findKth(nums1, i + k / 2, nums2, j, k - k / 2);
147-
return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
141+
int m = nums1.size(), n = nums2.size();
142+
function<int(int, int, int)> f = [&](int i, int j, int k) {
143+
if (i >= m) {
144+
return nums2[j + k - 1];
145+
}
146+
if (j >= n) {
147+
return nums1[i + k - 1];
148+
}
149+
if (k == 1) {
150+
return min(nums1[i], nums2[j]);
151+
}
152+
int p = k / 2;
153+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
154+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
155+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
156+
};
157+
int a = f(0, 0, (m + n + 1) / 2);
158+
int b = f(0, 0, (m + n + 2) / 2);
159+
return (a + b) / 2.0;
148160
}
149161
};
150162
```
@@ -154,9 +166,8 @@ public:
154166
```go
155167
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
156168
m, n := len(nums1), len(nums2)
157-
left, right := (m+n+1)/2, (m+n+2)/2
158-
var findKth func(i, j, k int) int
159-
findKth = func(i, j, k int) int {
169+
var f func(i, j, k int) int
170+
f = func(i, j, k int) int {
160171
if i >= m {
161172
return nums2[j+k-1]
162173
}
@@ -166,20 +177,21 @@ func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
166177
if k == 1 {
167178
return min(nums1[i], nums2[j])
168179
}
169-
midVal1 := math.MaxInt32
170-
midVal2 := math.MaxInt32
171-
if i+k/2-1 < m {
172-
midVal1 = nums1[i+k/2-1]
180+
p := k / 2
181+
x, y := 1<<30, 1<<30
182+
if ni := i + p - 1; ni < m {
183+
x = nums1[ni]
173184
}
174-
if j+k/2-1 < n {
175-
midVal2 = nums2[j+k/2-1]
185+
if nj := j + p - 1; nj < n {
186+
y = nums2[nj]
176187
}
177-
if midVal1 < midVal2 {
178-
return findKth(i+k/2, j, k-k/2)
188+
if x < y {
189+
return f(i+p, j, k-p)
179190
}
180-
return findKth(i, j+k/2, k-k/2)
191+
return f(i, j+p, k-p)
181192
}
182-
return (float64(findKth(0, 0, left)) + float64(findKth(0, 0, right))) / 2.0
193+
a, b := f(0, 0, (m+n+1)/2), f(0, 0, (m+n+2)/2)
194+
return float64(a+b) / 2.0
183195
}
184196
185197
func min(a, b int) int {
@@ -190,6 +202,102 @@ func min(a, b int) int {
190202
}
191203
```
192204

205+
### **TypeScript**
206+
207+
```ts
208+
function findMedianSortedArrays(nums1: number[], nums2: number[]): number {
209+
const m = nums1.length;
210+
const n = nums2.length;
211+
const f = (i: number, j: number, k: number): number => {
212+
if (i >= m) {
213+
return nums2[j + k - 1];
214+
}
215+
if (j >= n) {
216+
return nums1[i + k - 1];
217+
}
218+
if (k == 1) {
219+
return Math.min(nums1[i], nums2[j]);
220+
}
221+
const p = Math.floor(k / 2);
222+
const x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
223+
const y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
224+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
225+
};
226+
const a = f(0, 0, Math.floor((m + n + 1) / 2));
227+
const b = f(0, 0, Math.floor((m + n + 2) / 2));
228+
return (a + b) / 2;
229+
}
230+
```
231+
232+
### **JavaScript**
233+
234+
```js
235+
/**
236+
* @param {number[]} nums1
237+
* @param {number[]} nums2
238+
* @return {number}
239+
*/
240+
var findMedianSortedArrays = function (nums1, nums2) {
241+
const m = nums1.length;
242+
const n = nums2.length;
243+
const f = (i, j, k) => {
244+
if (i >= m) {
245+
return nums2[j + k - 1];
246+
}
247+
if (j >= n) {
248+
return nums1[i + k - 1];
249+
}
250+
if (k == 1) {
251+
return Math.min(nums1[i], nums2[j]);
252+
}
253+
const p = Math.floor(k / 2);
254+
const x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
255+
const y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
256+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
257+
};
258+
const a = f(0, 0, Math.floor((m + n + 1) / 2));
259+
const b = f(0, 0, Math.floor((m + n + 2) / 2));
260+
return (a + b) / 2;
261+
};
262+
```
263+
264+
### **TypeScript**
265+
266+
```ts
267+
public class Solution {
268+
private int m;
269+
private int n;
270+
private int[] nums1;
271+
private int[] nums2;
272+
273+
public double FindMedianSortedArrays(int[] nums1, int[] nums2) {
274+
m = nums1.Length;
275+
n = nums2.Length;
276+
this.nums1 = nums1;
277+
this.nums2 = nums2;
278+
int a = f(0, 0, (m + n + 1) / 2);
279+
int b = f(0, 0, (m + n + 2) / 2);
280+
return (a + b) / 2.0;
281+
}
282+
283+
private int f(int i, int j, int k) {
284+
if (i >= m) {
285+
return nums2[j + k - 1];
286+
}
287+
if (j >= n) {
288+
return nums1[i + k - 1];
289+
}
290+
if (k == 1) {
291+
return Math.Min(nums1[i], nums2[j]);
292+
}
293+
int p = k / 2;
294+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
295+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
296+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
297+
}
298+
}
299+
```
300+
193301
### **...**
194302

195303
```

‎solution/0000-0099/0004.Median of Two Sorted Arrays/README_EN.md

+155-50
Original file line numberDiff line numberDiff line change
@@ -48,52 +48,57 @@ Binary search.
4848
```python
4949
class Solution:
5050
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
51-
def findKth(i, j, k):
51+
def f(i: int, j: int, k: int) -> int:
5252
if i >= m:
5353
return nums2[j + k - 1]
5454
if j >= n:
5555
return nums1[i + k - 1]
5656
if k == 1:
5757
return min(nums1[i], nums2[j])
58-
midVal1 = nums1[i + k // 2 - 1] if i + k // 2 - 1 < m else inf
59-
midVal2 = nums2[j + k // 2 - 1] if j + k // 2 - 1 < n else inf
60-
if midVal1 < midVal2:
61-
return findKth(i + k // 2, j, k - k // 2)
62-
return findKth(i, j + k // 2, k - k // 2)
58+
p = k // 2
59+
x = nums1[i + p - 1] if i + p - 1 < m else inf
60+
y = nums2[j + p - 1] if j + p - 1 < n else inf
61+
return f(i + p, j, k - p) if x < y else f(i, j + p, k - p)
6362

6463
m, n = len(nums1), len(nums2)
65-
left, right = (m + n + 1) // 2, (m + n + 2) // 2
66-
return (findKth(0, 0, left) + findKth(0, 0, right)) / 2
64+
a = f(0, 0, (m + n + 1) // 2)
65+
b = f(0, 0, (m + n + 2) // 2)
66+
return (a + b) / 2
6767
```
6868

6969
### **Java**
7070

7171
```java
7272
class Solution {
73+
private int m;
74+
private int n;
75+
private int[] nums1;
76+
private int[] nums2;
77+
7378
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
74-
int m = nums1.length;
75-
int n = nums2.length;
76-
int left = (m + n + 1) / 2;
77-
int right = (m + n + 2) / 2;
78-
return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
79+
m = nums1.length;
80+
n = nums2.length;
81+
this.nums1 = nums1;
82+
this.nums2 = nums2;
83+
int a = f(0, 0, (m + n + 1) / 2);
84+
int b = f(0, 0, (m + n + 2) / 2);
85+
return (a + b) / 2.0;
7986
}
8087

81-
private int findKth(int[] nums1, int i, int[] nums2, int j, int k) {
82-
if (i >= nums1.length) {
88+
private int f(int i, int j, int k) {
89+
if (i >= m) {
8390
return nums2[j + k - 1];
8491
}
85-
if (j >= nums2.length) {
92+
if (j >= n) {
8693
return nums1[i + k - 1];
8794
}
8895
if (k == 1) {
8996
return Math.min(nums1[i], nums2[j]);
9097
}
91-
int midVal1 = (i + k / 2 - 1 < nums1.length) ? nums1[i + k / 2 - 1] : Integer.MAX_VALUE;
92-
int midVal2 = (j + k / 2 - 1 < nums2.length) ? nums2[j + k / 2 - 1] : Integer.MAX_VALUE;
93-
if (midVal1 < midVal2) {
94-
return findKth(nums1, i + k / 2, nums2, j, k - k / 2);
95-
}
96-
return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
98+
int p = k / 2;
99+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
100+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
101+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
97102
}
98103
}
99104
```
@@ -104,21 +109,25 @@ class Solution {
104109
class Solution {
105110
public:
106111
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
107-
int m = nums1.size();
108-
int n = nums2.size();
109-
int left = (m + n + 1) / 2;
110-
int right = (m + n + 2) / 2;
111-
return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
112-
}
113-
114-
int findKth(vector<int>& nums1, int i, vector<int>& nums2, int j, int k) {
115-
if (i >= nums1.size()) return nums2[j + k - 1];
116-
if (j >= nums2.size()) return nums1[i + k - 1];
117-
if (k == 1) return min(nums1[i], nums2[j]);
118-
int midVal1 = i + k / 2 - 1 < nums1.size() ? nums1[i + k / 2 - 1] : INT_MAX;
119-
int midVal2 = j + k / 2 - 1 < nums2.size() ? nums2[j + k / 2 - 1] : INT_MAX;
120-
if (midVal1 < midVal2) return findKth(nums1, i + k / 2, nums2, j, k - k / 2);
121-
return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
112+
int m = nums1.size(), n = nums2.size();
113+
function<int(int, int, int)> f = [&](int i, int j, int k) {
114+
if (i >= m) {
115+
return nums2[j + k - 1];
116+
}
117+
if (j >= n) {
118+
return nums1[i + k - 1];
119+
}
120+
if (k == 1) {
121+
return min(nums1[i], nums2[j]);
122+
}
123+
int p = k / 2;
124+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
125+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
126+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
127+
};
128+
int a = f(0, 0, (m + n + 1) / 2);
129+
int b = f(0, 0, (m + n + 2) / 2);
130+
return (a + b) / 2.0;
122131
}
123132
};
124133
```
@@ -128,9 +137,8 @@ public:
128137
```go
129138
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
130139
m, n := len(nums1), len(nums2)
131-
left, right := (m+n+1)/2, (m+n+2)/2
132-
var findKth func(i, j, k int) int
133-
findKth = func(i, j, k int) int {
140+
var f func(i, j, k int) int
141+
f = func(i, j, k int) int {
134142
if i >= m {
135143
return nums2[j+k-1]
136144
}
@@ -140,20 +148,21 @@ func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
140148
if k == 1 {
141149
return min(nums1[i], nums2[j])
142150
}
143-
midVal1 := math.MaxInt32
144-
midVal2 := math.MaxInt32
145-
if i+k/2-1 < m {
146-
midVal1 = nums1[i+k/2-1]
151+
p := k / 2
152+
x, y := 1<<30, 1<<30
153+
if ni := i + p - 1; ni < m {
154+
x = nums1[ni]
147155
}
148-
if j+k/2-1 < n {
149-
midVal2 = nums2[j+k/2-1]
156+
if nj := j + p - 1; nj < n {
157+
y = nums2[nj]
150158
}
151-
if midVal1 < midVal2 {
152-
return findKth(i+k/2, j, k-k/2)
159+
if x < y {
160+
return f(i+p, j, k-p)
153161
}
154-
return findKth(i, j+k/2, k-k/2)
162+
return f(i, j+p, k-p)
155163
}
156-
return (float64(findKth(0, 0, left)) + float64(findKth(0, 0, right))) / 2.0
164+
a, b := f(0, 0, (m+n+1)/2), f(0, 0, (m+n+2)/2)
165+
return float64(a+b) / 2.0
157166
}
158167
159168
func min(a, b int) int {
@@ -164,6 +173,102 @@ func min(a, b int) int {
164173
}
165174
```
166175

176+
### **TypeScript**
177+
178+
```ts
179+
function findMedianSortedArrays(nums1: number[], nums2: number[]): number {
180+
const m = nums1.length;
181+
const n = nums2.length;
182+
const f = (i: number, j: number, k: number): number => {
183+
if (i >= m) {
184+
return nums2[j + k - 1];
185+
}
186+
if (j >= n) {
187+
return nums1[i + k - 1];
188+
}
189+
if (k == 1) {
190+
return Math.min(nums1[i], nums2[j]);
191+
}
192+
const p = Math.floor(k / 2);
193+
const x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
194+
const y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
195+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
196+
};
197+
const a = f(0, 0, Math.floor((m + n + 1) / 2));
198+
const b = f(0, 0, Math.floor((m + n + 2) / 2));
199+
return (a + b) / 2;
200+
}
201+
```
202+
203+
### **JavaScript**
204+
205+
```js
206+
/**
207+
* @param {number[]} nums1
208+
* @param {number[]} nums2
209+
* @return {number}
210+
*/
211+
var findMedianSortedArrays = function (nums1, nums2) {
212+
const m = nums1.length;
213+
const n = nums2.length;
214+
const f = (i, j, k) => {
215+
if (i >= m) {
216+
return nums2[j + k - 1];
217+
}
218+
if (j >= n) {
219+
return nums1[i + k - 1];
220+
}
221+
if (k == 1) {
222+
return Math.min(nums1[i], nums2[j]);
223+
}
224+
const p = Math.floor(k / 2);
225+
const x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
226+
const y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
227+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
228+
};
229+
const a = f(0, 0, Math.floor((m + n + 1) / 2));
230+
const b = f(0, 0, Math.floor((m + n + 2) / 2));
231+
return (a + b) / 2;
232+
};
233+
```
234+
235+
### **TypeScript**
236+
237+
```ts
238+
public class Solution {
239+
private int m;
240+
private int n;
241+
private int[] nums1;
242+
private int[] nums2;
243+
244+
public double FindMedianSortedArrays(int[] nums1, int[] nums2) {
245+
m = nums1.Length;
246+
n = nums2.Length;
247+
this.nums1 = nums1;
248+
this.nums2 = nums2;
249+
int a = f(0, 0, (m + n + 1) / 2);
250+
int b = f(0, 0, (m + n + 2) / 2);
251+
return (a + b) / 2.0;
252+
}
253+
254+
private int f(int i, int j, int k) {
255+
if (i >= m) {
256+
return nums2[j + k - 1];
257+
}
258+
if (j >= n) {
259+
return nums1[i + k - 1];
260+
}
261+
if (k == 1) {
262+
return Math.Min(nums1[i], nums2[j]);
263+
}
264+
int p = k / 2;
265+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
266+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
267+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
268+
}
269+
}
270+
```
271+
167272
### **...**
168273

169274
```
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
1-
class Solution {
2-
public:
3-
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
4-
int m = nums1.size();
5-
int n = nums2.size();
6-
int left = (m + n + 1) / 2;
7-
int right = (m + n + 2) / 2;
8-
return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
9-
}
10-
11-
int findKth(vector<int>& nums1, int i, vector<int>& nums2, int j, int k) {
12-
if (i >= nums1.size()) return nums2[j + k - 1];
13-
if (j >= nums2.size()) return nums1[i + k - 1];
14-
if (k == 1) return min(nums1[i], nums2[j]);
15-
int midVal1 = i + k / 2 - 1 < nums1.size() ? nums1[i + k / 2 - 1] : INT_MAX;
16-
int midVal2 = j + k / 2 - 1 < nums2.size() ? nums2[j + k / 2 - 1] : INT_MAX;
17-
if (midVal1 < midVal2) return findKth(nums1, i + k / 2, nums2, j, k - k / 2);
18-
return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
19-
}
1+
class Solution {
2+
public:
3+
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
4+
int m = nums1.size(), n = nums2.size();
5+
function<int(int, int, int)> f = [&](int i, int j, int k) {
6+
if (i >= m) {
7+
return nums2[j + k - 1];
8+
}
9+
if (j >= n) {
10+
return nums1[i + k - 1];
11+
}
12+
if (k == 1) {
13+
return min(nums1[i], nums2[j]);
14+
}
15+
int p = k / 2;
16+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
17+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
18+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
19+
};
20+
int a = f(0, 0, (m + n + 1) / 2);
21+
int b = f(0, 0, (m + n + 2) / 2);
22+
return (a + b) / 2.0;
23+
}
2024
};
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,32 @@
1-
using System;
2-
using System.Linq;
3-
4-
class Range
5-
{
6-
public static Range Empty = new Range(new int[0], 0, -1);
7-
8-
public readonly int[] Numbers;
9-
public readonly int LeftIndex;
10-
public readonly int RightIndex;
11-
12-
public int Count { get { return RightIndex - LeftIndex + 1; } }
13-
14-
public int this[int index]
15-
{
16-
get
17-
{
18-
if (index >= Count)
19-
{
20-
throw new IndexOutOfRangeException();
21-
}
22-
return Numbers[LeftIndex + index];
23-
}
24-
}
25-
26-
public Range(int[] numbers) : this(numbers, 0, numbers.Length - 1)
27-
{
28-
}
29-
30-
public Range(int[] numbers, int leftIndex, int rightIndex)
31-
{
32-
Numbers = numbers;
33-
LeftIndex = leftIndex;
34-
RightIndex = rightIndex;
35-
if (RightIndex < LeftIndex) RightIndex = LeftIndex - 1;
36-
}
37-
38-
public Range GetSubRange(int lowerBound, int upperBound)
39-
{
40-
if (lowerBound > upperBound) return Empty;
41-
var leftIndex = lowerBound == int.MinValue ? LeftIndex : Search(lowerBound);
42-
var rightIndex = upperBound == int.MaxValue ? RightIndex : Search(upperBound + 1) - 1;
43-
return new Range(Numbers, leftIndex, rightIndex);
44-
}
45-
46-
private int Search(int target)
47-
{
48-
var l = 0;
49-
var r = Numbers.Length - 1;
50-
while (l < r)
51-
{
52-
var mid = (l + r) / 2;
53-
if (Numbers[mid] < target)
54-
{
55-
l = mid + 1;
56-
}
57-
else
58-
{
59-
r = mid;
60-
}
61-
}
62-
return Numbers[l] >= target ? l : l + 1;
63-
}
64-
}
65-
66-
public class Solution {
67-
public double FindMedianSortedArrays(int[] nums1, int[] nums2)
68-
{
69-
var totalNumbers = nums1.Length + nums2.Length;
70-
var targetOrder1 = (totalNumbers + 1)/2;
71-
var targetOrder2 = (totalNumbers + 2)/2;
72-
var range1 = new Range(nums1);
73-
var range2 = new Range(nums2);
74-
var number1 = FindMedianSortedArrays(range1, range2, targetOrder1);
75-
var number2 = targetOrder1 == targetOrder2 ? number1 : FindMedianSortedArrays(range1, range2, targetOrder2);
76-
return ((double) number1 + number2)/2;
77-
}
78-
79-
private int FindMedianSortedArrays(Range range1, Range range2, int targetOrder)
80-
{
81-
if (range1.Count == 0)
82-
{
83-
return range2[targetOrder - 1];
84-
}
85-
if (range2.Count == 0)
86-
{
87-
return range1[targetOrder - 1];
88-
}
89-
90-
var midNumber = range1[(range1.Count - 1)/2];
91-
var midRanges = new[] { range1.GetSubRange(midNumber, midNumber), range2.GetSubRange(midNumber, midNumber) };
92-
var leftRanges = new[]
93-
{
94-
new Range(range1.Numbers, range1.LeftIndex, midRanges[0].LeftIndex - 1),
95-
new Range(range2.Numbers, range2.LeftIndex, midRanges[1].LeftIndex - 1)
96-
};
97-
var rightRanges = new[]
98-
{
99-
new Range(range1.Numbers, midRanges[0].RightIndex + 1, range1.RightIndex),
100-
new Range(range2.Numbers, midRanges[1].RightIndex + 1, range2.RightIndex)
101-
};
102-
103-
var leftCount = leftRanges.Sum(r => r.Count);
104-
var midCount = midRanges.Sum(r => r.Count);
105-
var rightCount = rightRanges.Sum(r => r.Count);
106-
107-
if (leftCount == 0 && rightCount == 0)
108-
{
109-
return midNumber;
110-
}
111-
if (leftCount >= targetOrder)
112-
{
113-
return FindMedianSortedArrays(leftRanges[0], leftRanges[1], targetOrder);
114-
}
115-
if (leftCount + midCount >= targetOrder)
116-
{
117-
return FindMedianSortedArrays(midRanges[0], midRanges[1], targetOrder - leftCount);
118-
}
119-
return FindMedianSortedArrays(rightRanges[0], rightRanges[1], targetOrder - leftCount - midCount);
120-
}
1+
public class Solution {
2+
private int m;
3+
private int n;
4+
private int[] nums1;
5+
private int[] nums2;
6+
7+
public double FindMedianSortedArrays(int[] nums1, int[] nums2) {
8+
m = nums1.Length;
9+
n = nums2.Length;
10+
this.nums1 = nums1;
11+
this.nums2 = nums2;
12+
int a = f(0, 0, (m + n + 1) / 2);
13+
int b = f(0, 0, (m + n + 2) / 2);
14+
return (a + b) / 2.0;
15+
}
16+
17+
private int f(int i, int j, int k) {
18+
if (i >= m) {
19+
return nums2[j + k - 1];
20+
}
21+
if (j >= n) {
22+
return nums1[i + k - 1];
23+
}
24+
if (k == 1) {
25+
return Math.Min(nums1[i], nums2[j]);
26+
}
27+
int p = k / 2;
28+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
29+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
30+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
31+
}
12132
}

‎solution/0000-0099/0004.Median of Two Sorted Arrays/Solution.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
22
m, n := len(nums1), len(nums2)
3-
left, right := (m+n+1)/2, (m+n+2)/2
4-
var findKth func(i, j, k int) int
5-
findKth = func(i, j, k int) int {
3+
var f func(i, j, k int) int
4+
f = func(i, j, k int) int {
65
if i >= m {
76
return nums2[j+k-1]
87
}
@@ -12,20 +11,21 @@ func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
1211
if k == 1 {
1312
return min(nums1[i], nums2[j])
1413
}
15-
midVal1 := math.MaxInt32
16-
midVal2 := math.MaxInt32
17-
if i+k/2-1 < m {
18-
midVal1 = nums1[i+k/2-1]
14+
p := k / 2
15+
x, y := 1<<30, 1<<30
16+
if ni := i + p - 1; ni < m {
17+
x = nums1[ni]
1918
}
20-
if j+k/2-1 < n {
21-
midVal2 = nums2[j+k/2-1]
19+
if nj := j + p - 1; nj < n {
20+
y = nums2[nj]
2221
}
23-
if midVal1 < midVal2 {
24-
return findKth(i+k/2, j, k-k/2)
22+
if x < y {
23+
return f(i+p, j, k-p)
2524
}
26-
return findKth(i, j+k/2, k-k/2)
25+
return f(i, j+p, k-p)
2726
}
28-
return (float64(findKth(0, 0, left)) + float64(findKth(0, 0, right))) / 2.0
27+
a, b := f(0, 0, (m+n+1)/2), f(0, 0, (m+n+2)/2)
28+
return float64(a+b) / 2.0
2929
}
3030

3131
func min(a, b int) int {
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
1-
class Solution {
2-
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
3-
int m = nums1.length;
4-
int n = nums2.length;
5-
int left = (m + n + 1) / 2;
6-
int right = (m + n + 2) / 2;
7-
return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
8-
}
9-
10-
private int findKth(int[] nums1, int i, int[] nums2, int j, int k) {
11-
if (i >= nums1.length) {
12-
return nums2[j + k - 1];
13-
}
14-
if (j >= nums2.length) {
15-
return nums1[i + k - 1];
16-
}
17-
if (k == 1) {
18-
return Math.min(nums1[i], nums2[j]);
19-
}
20-
int midVal1 = (i + k / 2 - 1 < nums1.length) ? nums1[i + k / 2 - 1] : Integer.MAX_VALUE;
21-
int midVal2 = (j + k / 2 - 1 < nums2.length) ? nums2[j + k / 2 - 1] : Integer.MAX_VALUE;
22-
if (midVal1 < midVal2) {
23-
return findKth(nums1, i + k / 2, nums2, j, k - k / 2);
24-
}
25-
return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
26-
}
1+
class Solution {
2+
private int m;
3+
private int n;
4+
private int[] nums1;
5+
private int[] nums2;
6+
7+
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
8+
m = nums1.length;
9+
n = nums2.length;
10+
this.nums1 = nums1;
11+
this.nums2 = nums2;
12+
int a = f(0, 0, (m + n + 1) / 2);
13+
int b = f(0, 0, (m + n + 2) / 2);
14+
return (a + b) / 2.0;
15+
}
16+
17+
private int f(int i, int j, int k) {
18+
if (i >= m) {
19+
return nums2[j + k - 1];
20+
}
21+
if (j >= n) {
22+
return nums1[i + k - 1];
23+
}
24+
if (k == 1) {
25+
return Math.min(nums1[i], nums2[j]);
26+
}
27+
int p = k / 2;
28+
int x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
29+
int y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
30+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
31+
}
2732
}
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,27 @@
11
/**
22
* @param {number[]} nums1
33
* @param {number[]} nums2
4-
* @return {number} 012345
4+
* @return {number}
55
*/
66
var findMedianSortedArrays = function (nums1, nums2) {
7-
if (nums1.length == 0 || nums2.length == 0) {
8-
if ((nums1.length + nums2.length) % 2 == 1) {
9-
const index = parseInt((nums1.length + nums2.length) / 2);
10-
return nums2.length == 0 ? nums1[index] : nums2[index];
11-
} else {
12-
let nums = nums2.length == 0 ? nums1 : nums2;
13-
const index = nums.length / 2;
14-
return (nums[index - 1] + nums[index]) / 2;
7+
const m = nums1.length;
8+
const n = nums2.length;
9+
const f = (i, j, k) => {
10+
if (i >= m) {
11+
return nums2[j + k - 1];
1512
}
16-
}
17-
18-
if (nums1.length > nums2.length) {
19-
swap(nums1, nums2);
20-
}
21-
const M = nums1.length,
22-
N = nums2.length;
23-
let min = 0,
24-
max = M,
25-
half = parseInt((M + N + 1) / 2); // 连个数组合并的中间值
26-
while (min <= max) {
27-
let i = parseInt((min + max) / 2); // nums1 的索引值
28-
let j = half - i; // num2 的索引值
29-
if (i < max && nums2[j - 1] > nums1[i]) {
30-
min++;
31-
} else if (i > min && nums1[i - 1] > nums2[j]) {
32-
max--;
33-
} else {
34-
let maxLeft = 0;
35-
if (i == 0) {
36-
maxLeft = nums2[j - 1];
37-
} else if (j == 0) {
38-
maxLeft = nums1[i - 1];
39-
} else {
40-
maxLeft = Math.max(nums1[i - 1], nums2[j - 1]);
41-
}
42-
if ((M + N) % 2 == 1) {
43-
return maxLeft;
44-
}
45-
let minRight = 0;
46-
if (i == M) {
47-
minRight = nums2[j];
48-
} else if (j == N) {
49-
minRight = nums1[i];
50-
} else {
51-
minRight = Math.min(nums1[i], nums2[j]);
52-
}
53-
return (maxLeft + minRight) / 2;
13+
if (j >= n) {
14+
return nums1[i + k - 1];
5415
}
55-
}
56-
return 0;
16+
if (k == 1) {
17+
return Math.min(nums1[i], nums2[j]);
18+
}
19+
const p = Math.floor(k / 2);
20+
const x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
21+
const y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
22+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
23+
};
24+
const a = f(0, 0, Math.floor((m + n + 1) / 2));
25+
const b = f(0, 0, Math.floor((m + n + 2) / 2));
26+
return (a + b) / 2;
5727
};
58-
59-
function swap(a, b) {
60-
let tmp = a;
61-
a = b;
62-
b = tmp;
63-
}
64-
65-
const nums1 = [4, 5];
66-
const nums2 = [1, 2, 3];
67-
findMedianSortedArrays(nums1, nums2);
68-
69-
/**
70-
* 实现思路
71-
* 先排除空数组的情况
72-
* 数组从小到大排序
73-
* 取小数组的中间值
74-
* 取大数组的索引 = 总中间值-小数组中间值
75-
* 循环直到符合条件
76-
* 如果都不符合条件,那么说明中间值在两个数组的左边或者右边
77-
*/
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
class Solution:
2-
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
3-
def findKth(i, j, k):
4-
if i >= m:
5-
return nums2[j + k - 1]
6-
if j >= n:
7-
return nums1[i + k - 1]
8-
if k == 1:
9-
return min(nums1[i], nums2[j])
10-
midVal1 = nums1[i + k // 2 - 1] if i + k // 2 - 1 < m else inf
11-
midVal2 = nums2[j + k // 2 - 1] if j + k // 2 - 1 < n else inf
12-
if midVal1 < midVal2:
13-
return findKth(i + k // 2, j, k - k // 2)
14-
return findKth(i, j + k // 2, k - k // 2)
15-
16-
m, n = len(nums1), len(nums2)
17-
left, right = (m + n + 1) // 2, (m + n + 2) // 2
18-
return (findKth(0, 0, left) + findKth(0, 0, right)) / 2
1+
class Solution:
2+
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
3+
def f(i: int, j: int, k: int) -> int:
4+
if i >= m:
5+
return nums2[j + k - 1]
6+
if j >= n:
7+
return nums1[i + k - 1]
8+
if k == 1:
9+
return min(nums1[i], nums2[j])
10+
p = k // 2
11+
x = nums1[i + p - 1] if i + p - 1 < m else inf
12+
y = nums2[j + p - 1] if j + p - 1 < n else inf
13+
return f(i + p, j, k - p) if x < y else f(i, j + p, k - p)
14+
15+
m, n = len(nums1), len(nums2)
16+
a = f(0, 0, (m + n + 1) // 2)
17+
b = f(0, 0, (m + n + 2) // 2)
18+
return (a + b) / 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
function findMedianSortedArrays(nums1: number[], nums2: number[]): number {
2+
const m = nums1.length;
3+
const n = nums2.length;
4+
const f = (i: number, j: number, k: number): number => {
5+
if (i >= m) {
6+
return nums2[j + k - 1];
7+
}
8+
if (j >= n) {
9+
return nums1[i + k - 1];
10+
}
11+
if (k == 1) {
12+
return Math.min(nums1[i], nums2[j]);
13+
}
14+
const p = Math.floor(k / 2);
15+
const x = i + p - 1 < m ? nums1[i + p - 1] : 1 << 30;
16+
const y = j + p - 1 < n ? nums2[j + p - 1] : 1 << 30;
17+
return x < y ? f(i + p, j, k - p) : f(i, j + p, k - p);
18+
};
19+
const a = f(0, 0, Math.floor((m + n + 1) / 2));
20+
const b = f(0, 0, Math.floor((m + n + 2) / 2));
21+
return (a + b) / 2;
22+
}

0 commit comments

Comments
 (0)
Please sign in to comment.