我正在练习接受一家大型在线零售商的采访,现在正试图为“两个排序数组的中位数”问题提出一个优雅的解决方案。我知道youtube上提出的解决方案,但我正在尝试编写另一种解决方案。我写了
include <stdio.h>
int M2SA ( int * A, int m, int * B, int n )
{
/* Returns the median of two sorted arrays A and B of lengths m and n respectively.
Assumes A and B aren't both empty.
*/
int ida = 0, idb = 0, idmed = (m+n)/2;
while ((ida + idb) != idmed)
{
if (A[ida] < B[idb])
++ida;
else
++idb;
}
return (A[ida] < A[idb] ? A[ida] : B[idb]);
}
int main()
{
int arr1 [] = {1, 1, 59, 69};
int arr2 [] = {-4, 0, 49, 59, 59, 59};
printf("%d", M2SA(arr1, sizeof(arr1)/sizeof(int), arr2, sizeof(arr2)/sizeof(int)));
return 0;
}
打印出正确答案(59
),但我发现有一个缺陷,即我的算法仅在idmed
不大于m
或n
时才有效。例如,如果数组是{1}
和{69, 293, 393, 1923129}
,则在ida
循环的第一次迭代后1
等于while
,因此第二次迭代while循环尝试访问A[1]
。但是,我想不出一个简单的解决方法来添加到我的代码中。有一个简单的吗?
答案 0 :(得分:3)
以下是对您的解决方案的优雅修复:
int ida = 0, idb = 0, idmed = (m + n) / 2;
while (ida < m && idb < n && ida + idb < idmed) {
A[ida] < B[idb] ? ++ida : ++idb;
}
if (ida == m) return B[idmed - m];
if (idb == n) return A[idmed - n];
return A[ida] < B[idb] ? A[ida] : B[idb];
答案 1 :(得分:2)
基本上有3种情况需要考虑:
实施必须了解这3个案例。 触发3种情况中的哪一种取决于输入数据。
例如,如果所有较小的值都在数组1中,并且数组2中的较大值和数组1的长度短于数组2的长度,则数组1中的索引处于数组1的长度。所以访问它不是一个好主意。
这是一个使用for循环而不是while的实现。我更喜欢在这里循环,因为更容易看到循环最终会终止。
main()函数包含一组测试用例,它们触发上述所有三个代码路径。
int
m2a
( _In_reads_(s1) const int * a1
, int s1
, _In_reads_(s2) const int *a2
, int s2
)
{
int mi = (s1 + s2) / 2;
int ai1 = 0;
int ai2 = 0;
for (int i = 0; i < mi;i++)
{
if (ai1 < s1 && ai2 < s2)
{
if (a1[ai1] < a2[ai2])
{
ai1++;
}
else
{
ai2++;
}
}
else
{
if (ai1 < s1)
{
ai1++;
}
if (ai2 < s2)
{
ai2++;
}
}
}
int result = 0;
if (ai1 < s1 && ai2 < s2)
{
result = a1[ai1] < a2[ai2] ? a1[ai1] : a2[ai2];
}
else
{
if (ai1 < s1)
{
result = a1[ai1];
}
if (ai2 < s2)
{
result = a2[ai2];
}
}
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
{
const int s1 = 4;
const int s2 = 4;
int a1[s1] = { 1, 2, 3, 4 };
int a2[s2] = { 1, 2, 3, 4 };
int m = m2a(a1, s1, a2, s2);
printf("%d\n", m);
}
{
const int s1 = 5;
const int s2 = 4;
int a1[s1] = { 5,6,7,8,9 };
int a2[s2] = { 1, 2, 3, 4 };
int m = m2a(a1, s1, a2, s2);
printf("%d\n", m);
}
{
const int s1 = 4;
const int s2 = 5;
int a1[s1] = { 1, 2, 3, 4 };
int a2[s2] = { 5, 6, 7, 8, 9 };
int m = m2a(a1, s1, a2, s2);
printf("%d\n", m);
}
{
const int s1 = 1;
const int s2 = 5;
int a1[s1] = { 99 };
int a2[s2] = { 5, 6, 7, 8, 9 };
int m = m2a(a1, s1, a2, s2);
printf("%d\n", m);
}
{
const int s1 = 5;
const int s2 = 1;
int a1[s1] = { 5, 6, 7, 8, 9 };
int a2[s2] = { 99 };
int m = m2a(a1, s1, a2, s2);
printf("%d\n", m);
}
{
const int s1 = 5;
const int s2 = 5;
int a1[s1] = { 1,1,1,1,1 };
int a2[s2] = { 1,1,1,1,1 };
int m = m2a(a1, s1, a2, s2);
printf("%d\n", m);
}
{
const int s1 = 5;
const int s2 = 1;
int a1[s1] = { 5, 6, 7, 8, 9 };
int a2[s2] = { 3 };
int m = m2a(a1, s1, a2, s2);
printf("%d\n", m);
}
return 0;
}
修复剩余的bug。脑死亡“优雅”。如果你有3个案例,试图隐藏它是危险的。所以,循环体也显示了3个案例......
答案 2 :(得分:0)
也许你可以改变:
if (A[ida] < B[idb])
要:
if (ida < m && A[ida] < B[idb])
和
return (A[ida] < A[idb] ? A[ida] : B[idb]);
要:
return (ida < m && A[ida] < A[idb] ? A[ida] : B[idb]);