检查两个数组中的相似元素,为某些测试返回正确的值,为其他测试返回不正确的值

Checking two arrays for similar elements, returns correct values for some tests, incorrect for others

本文关键字:返回 测试 不正确 其他 元素 两个 相似 数组 检查      更新时间:2023-10-16

我有一个函数,它打算查看两个数组是否包含相似的元素。

这是主要功能:

int arr[] = {1, 2, 2};
int arrb[] = {1, 2, 1};
int a = (sizeof(arr)/sizeof(arr[0]));
int b = (sizeof(arrb)/sizeof(arrb[0]));
cout << checkForSimilar(arr,arrb,a,b);

和以下功能:

int checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
    if (a != b) return 0; else
    {
        int foundSwitch = 0;
        int found = 0;
        for (int i = 0; i < a; i++)
        {
            for (int j = 0; j < b; j++)
            {
                if (arraya[i] == arrayb[j])
                {
                    foundSwitch = 1;
                    break;
                } else foundSwitch = 0;
            }
        }
        return foundSwitch;
    }
}

但是,该函数不会返回预期值。例如,在上面的示例中,它应该返回 0,但它返回 1。此函数为某些数组返回正确的值,而不是为其他数组返回正确的值。我不明白我在这里做错了什么。

编辑:我对上述功能的措辞很差。这是一个相等性测试,其中两个数组需要包含相同的元素。但是,它们不必按相同的顺序排列。

最简单和更有效的是在比较之前排序(n log n vs ):

bool checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
    std::sort(arraya, arraya + a);
    std::sort(arrayb, arrayb + b);
    return a == b && std::equal(arraya, arraya + a, arrayb);
}

演示

首先,当代码发现一个相似之处时,代码会中断。如果要检查两个数组是否具有相同的元素(并且处于相同的位置),则可能需要像这样更改它:

if (a != b) 
    return 0; 
else
{
    int foundSwitch = 0;
    int found = 0;
    for (int i = 0; i < a; i++)
    {
        if (arraya[i] != arrayb[i])
        {
            foundSwitch = 0;
            break;
        }
        else foundSwitch = 1;
    }
    return foundSwitch;
}

仅当元素及其顺序相同时,此代码才有效(例如 {3, 2, 1} 和 {1, 2, 3} 将返回 0)。

如果您不关心顺序,则可以使用 for 循环。

if (a != b) 
    return 0; 
else
{
    int foundSwitch;
    int numToCheck;
    for (int i = 0; i < a; i++)
    {
        numToCheck = arraya[i];
        foundSwitch = 0;
        for (int j = 0; j < b; j++)
        {
            if (numToCheck == arrayb[j])
            {
                foundSwitch = 1;
                break;
            }
        }
        if (foundSwitch == 0)
            break;
    }
    return foundSwitch;
}

基本上,这会检查数组 A 中的 i 元素。如果该元素在数组 B 中,则 in 中断内部 j 循环并将找到的开关设置为 1。默认情况下,它将是 0,所以如果在 j 循环结束时它保持不变,那么您会在数组 a 中找到一个不在 b 中的元素。

你的代码必须是:'int checkForSimilar(int arraya[], int arrayb[], int a, int b)

{
    if (a != b) return 0; else
    {
        int foundSwitch = 1;
        int found = 0;
        for (int i = 0; i < a; i++)
        {
            for (int j = 0; j < b; j++)
            {
                if (arraya[i] == arrayb[j])
                {
                    foundSwitch = 0;
                    break;
                }
            }
            if(foundSwitch == 0){
                break;
            }
        }
        return foundSwitch;
    }
}`

您编写的函数表示两个数组相似,因为您只需检查第一个数组中的每个元素是否存在于第二个数组中。在您在此处放置的测试示例中,情况就是如此,因此您得到 1 作为返回。

由于您希望数组中的每个元素都与另一个元素的一个元素完全匹配,因此您应该这样做:

    int foundSwitch = 0;
    int found = 0;
    for (int i = 0; i < a; i++)
    {
        for (int j = i; j < b; j++)
        {
            if (arraya[i] == arrayb[j])
            {
                foundSwitch = 1;
                int temp = arrayb[i];
                arrayb[i]=arrayb[j];
                arrayb[j]=temp;
                break;
            } else foundSwitch = 0;
        }
    }
    free[] foundvalues;
    return foundSwitch;
<</div> div class="answers">

正如我上面评论的,你只是在检查另一个数组中是否存在一个数组的元素。例如,对于 [1,1,2,2] 和 [1,2,1,1] 它将失败,最简单的方法是先对两个数组进行排序,然后逐个比较它们的元素

int compare_int( const void* a, const void* b )
{
    if( *(int*)a == *(int*)b ) return 0;
    return *(int*)a < *(int*)b ? -1 : 1;
}

int checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
  if (a != b) {
   return 0;
  }
  qsort(arraya, a, sizeof(int), compare_int); // O(n logn)
  qsort(arrayb, b, sizeof(int), compare_int); // O(n logn)
  for (int index = 0; index < a; ++index) {  // O(n)
    if (arraya[index] != arrayb[index]) {
      return 0;
    }
  }
  return 1;
}

即使在复杂性方面,它的 O(nlogn),也比嵌套的循环要好,后者将是 O(n2)。

编辑:按照PaulMcKenzie的建议使用std::sort

int checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
  if (a != b) {
   return 0;
  }
  std::sort(std::begin(arraya), std::end(arraya));
  std::sort(std::begin(arrayb), std::end(arrayb));
  for (int index = 0; index < a; ++index) {
    if (arraya[index] != arrayb[index]) {
      return 0;
    }
  }
  return 1;
}

一种可能更有效的方法是使用 STL 算法
作为下面的示例,它复制数组以防止原始数组被编辑,然后在检查std::equal之前使用 std::sort 进行排序

bool isSimilar(int arr[], const int& size1, int arr2[], const int& size2)
{
    int temp1[size1];
    int temp2[size2];
    copy(arr, arr + size1, temp1);   // copy values into temps to avoid
    copy(arr2, arr2 + size2, temp2); // editing to the originals
    sort(temp1, temp1 + size1);      // Sort for performance
    sort(temp2, temp2 + size2);
    if (equal(temp1, temp1 + size1, temp2))
        return 1;
    else
        return 0;
}
int main()
{
    int arr[]  {1,2,3,4,5,6,7,8,9};
    int arr2[] {9,8,7,6,5,4,3,2,1};
    const int size1 = (sizeof(arr)/sizeof(*arr));
    const int size2 = (sizeof(arr2)/sizeof(*arr2));
    cout << (isSimilar(arr, size1, arr2, size2) ? "Similar" : "Not similar");
}

当函数返回时,原始元素保持不变。
这段代码不仅速度更快,而且提高了可读性,看起来更优雅。