关于比较两个无序数组并删除 a[] 中可以在 b[] 中找到的元素的问题

Question about comparing two unordered arrays and removing elements in a[] that can be found in b[]

本文关键字:问题 元素 删除 比较 于比较 两个 数组 无序      更新时间:2023-10-16

有一个问题我无法解决。这里有两个无序数组

int a1[] = { 5, 7, 14, 0, 6, 2, 9, 11, 3 }; int n = 9;
int b[] = { 6, 4, 3, 10, 9, 15, 7 }; int m = 7;

我想比较它们并删除 a[] 中可以在 b[] 中找到的元素。下面的代码向我返回一个正确的值 n。正确的值应该是 4,但即使我成功对数组 a1[] 进行排序,它也给了我 5。它给了我这样的结果:

a1[] = { 5, 2, 14, 0 ,11 }

我的结果和模型答案之间略有不同。我的意思是 a1[] 中元素的顺序。模型答案是

a1[] = {5, 11, 14, 0, 2}

你们能帮我找出问题吗?

int removeAll_unordered(int *a, int& n, const int *b, int m) 
{
for (int i = 0; i < m; i++) {
int j = 0;
for (j = 0; j < n; j++)
{
if (b[i] == a[j])
{
a[j] = a[n - 1];
n -= 1;
}
}
}
return n;
}

如果你用C++编写代码,你应该使用标准库为你提供的东西 - 在你的例子中std::vectorstd::remove_if算法:

void removeAll_unordered( std::vector<int> &a, const std::vector<int> &b )
{
auto end = std::remove_if( a.begin(), a.end(), [b]( int i ) {
return std::find( b.begin(), b.end(), i ) != b.end();
} );
a.erase( end, a.end() );
}

实时代码 1

但是这种用法效率非常低,因此使用提供std::unordered_set又名哈希集的标准库,我们可以轻松地对其进行优化:

void removeAll_unordered( std::vector<int> &a, const std::vector<int> &b )
{
auto end = std::remove_if( a.begin(), a.end(), 
[set = std::unordered_set<int>( b.begin(), b.end() )]( int i ) {
return set.count( i );
} );
a.erase( end, a.end() );
}

实时代码 2

我在你的代码中发现了一个问题,虽然我无法编译,但它应该可以工作。

在您的代码中,

if (b[i] == a[j])
{
a[j] = a[n - 1];
n -= 1;
}

当在a中找到b中的元素时,您将该值替换为a[n-1],这没关系,但是该值没有与b[i]进行比较,因为j增加了,所以我更正了这部分。如果使用不同的输入运行,您将能够发现此问题。

int removeAll_unordered(int *a, int& n, const int *b, int m) 
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n;)
{
if (a[j] == b[i]) // replace a[j] with a[n-1] and decrease n
{
a[j] = a[n - 1];
n--;
}
else
j++; //  otherwise increase j
}
}
return n;
}

获得确切答案(删除后元素在a中的顺序(

以下是修改后的代码:

int duplicates = 0;   //  counts total numbers that removed from a[] 
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m;)
{
if (a[i] == b[j]) // replace a[j] with a[n-1] and decrease n
{
if (i == n - 1) // when we reach the last element of a that matches in b
{
n--;              //  updating length of a[] 
duplicates++;     //  one more removed
break;
}
a[i] = a[n - 1];
n--;                 //  updating length of a[] 
duplicates++;        //  one more removed
j = 0;
}
else
j++; // otherwise increase j
}
}
return duplicates;        //  returned total removed numbers
  • 我发现了你的代码的问题。更改 for 循环中的变量。第一个 for 循环使用"n"变量作为其最大值,第二个循环使用"m"值。

  • 然后你只减少了n个值,但没有检查新的第i个值。因为现在 i 第 i 个值发生了变化。因此,您还想再次检查该值。为此,您也可以减少"i"值。

  • 而且你上面提到的你的答案是 5 而不是 4。然后它正确回答。因为您在编写此代码时考虑了数组的 9 个元素。不是 0 到 8。所以,如果你写这段代码时考虑0到8个元素,你可以得到你想要的任何东西。如果你想要 4,你可以将最终值减少 1。然后你就可以得到你的价值。

修改后的电源线如下。

for (int i = 0; i < n; i++) 
{
for (int j = 0; j < m; j++)
{
if (b[j] == a[i])
{
a[i] = a[n - 1];
n -= 1;
i = i - 1;
}
}
}
return n;