需要帮助为我的算法中的缺陷提供优雅的修复

Need help coming up with elegant fix for flaw in my algorithm

本文关键字:缺陷 帮助 我的 算法      更新时间:2023-10-16

我正在为一家大型在线零售商的面试进行练习,现在正试图为"两个排序数组的中值"问题找到一个优雅的解决方案。我知道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不大于mn时才有效。例如,如果数组是{1}{69, 293, 393, 1923129},则在while循环的第一次迭代之后,ida等于1,因此while循环的第二次迭代尝试访问A[1]。然而,我想不出一个简单的修复程序可以添加到我的代码中。有简单的吗?

以下是对您的解决方案的一个优雅修复:

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];

基本上有3种情况需要考虑:

  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("%dn", 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("%dn", 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("%dn", 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("%dn", 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("%dn", 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("%dn", 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("%dn", m);
}
return 0;
}

修复了剩余的错误。脑死亡胜过"优雅"。如果你有3种情况,试图隐藏它是危险的。因此,环的身体也显示了这3种情况。。。

也许您可以更改:

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]);