Skip to content

Commit 7ec8301

Browse files
committed
4.寻找两个有序数组的中位数,双指针,二分查找
1 parent 29de968 commit 7ec8301

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

leetcode_Java/Solution0004.java

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,97 @@ public double findMedianSortedArrays(int[] nums1, int[] nums2) {
4545
return nums3[n / 2];
4646
}
4747
}
48+
}
49+
50+
51+
/*
52+
双指针:遍历比较两个数组元素,根据奇偶个数找到整体中间位置,计算中位数
53+
*/
54+
class Solution {
55+
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
56+
int m = nums1.length, n = nums2.length;
57+
int len = m + n;
58+
int left = -1, right = - 1;
59+
int index1 = 0, index2 = 0;
60+
for (int i = 0; i <= len / 2; i++) {
61+
left = right;
62+
if (index1 < m && (index2 >= n || nums1[index1] < nums2[index2])) {
63+
right = nums1[index1++];
64+
} else {
65+
right = nums2[index2++];
66+
}
67+
}
68+
if (len % 2 == 0) {
69+
return (left + right) / 2.0;
70+
}
71+
return right;
72+
}
73+
}
74+
75+
76+
/*
77+
二分查找:
78+
1、一个长度为 m 的数组,有 0 到 m 总共 m + 1 个位置可以切。我们把数组 A 和数组 B 分别在 i 和 j 进行切割
79+
2、将 i 的左边和 j 的左边组合成「左半部分」,将 i 的右边和 j 的右边组合成「右半部分」
80+
1)当 A 数组和 B 数组的总长度是偶数时,如果我们能够保证 左半部分的长度等于右半部分 i+j = m-i + n-j,也就是 j = (m+n)/2 - i,
81+
且左半部分最大的值小于等于右半部分最小的值,max(A[i-1],B[j-1])) <= min(A[i],B[j]))
82+
那么 中位数 = (左半部分最大值 + 右半部分最小值) / 2 = (max(A[i-1],B[j-1]) + min(A[i],B[j])) / 2
83+
2)当 A 数组和 B 数组的总长度是奇数时,如果我们能够保证 左半部分的长度比右半部分大 1, i+j = m-i + n-j + 1,也就是 j = (m+n+1)/2 - i,
84+
且左半部分最大的值小于等于右半部分最小的值,max(A[i-1],B[j-1])) <= min(A[i],B[j]))
85+
那么 中位数 = 左半部分最大值 = max(A[i-1],B[j-1])
86+
3、增加 i 的方式用二分,初始化 i 为中间的值,然后减半找中间的,直到找到答案
87+
4、时间复杂度:我们对较短的数组进行了二分查找,所以时间复杂度是 O(log(min(m,n))
88+
空间复杂度:只有一些固定的变量,和数组长度无关,所以空间复杂度是 O(1)
89+
90+
A: 2 4 6 | 8 10 12 14
91+
iMin i iMax
92+
B: 1 5 8 10 11 | 12 12 15
93+
j
94+
=================================
95+
A: 2 4 6 8 10 | 12 14
96+
iMin i iMax
97+
B: 1 5 8 | 10 11 12 12 15
98+
j
99+
*/
100+
class Solution {
101+
public double findMedianSortedArrays(int[] A, int[] B) {
102+
int m = A.length;
103+
int n = B.length;
104+
if (m > n) {
105+
return findMedianSortedArrays(B, A);
106+
}
107+
int iMin = 0, iMax = m;
108+
while (iMin <= iMax) {
109+
int i = (iMin + iMax) / 2;
110+
int j = (m + n + 1) / 2 - i;
111+
if (j != 0 && i != m && B[j - 1] > A[i]) {
112+
iMin = i + 1;
113+
} else if (i != 0 && j != n && A[i - 1] > B[j]) {
114+
iMax = i - 1;
115+
} else {
116+
int maxLeft = 0;
117+
if (i == 0) {
118+
maxLeft = B[j - 1];
119+
} else if (j == 0) {
120+
maxLeft = A[i - 1];
121+
} else {
122+
maxLeft = Math.max(A[i - 1], B[j - 1]);
123+
}
124+
if ((m + n) % 2 == 1) {
125+
return maxLeft;
126+
}
127+
128+
int minRight = 0;
129+
if (i == m) {
130+
minRight = B[j];
131+
} else if (j == n) {
132+
minRight = A[i];
133+
} else {
134+
minRight = Math.min(B[j], A[i]);
135+
}
136+
return (maxLeft + minRight) / 2.0;
137+
}
138+
}
139+
return 0.0;
140+
}
48141
}

0 commit comments

Comments
 (0)