给定一个整数向量,我想写一个快速(不明显的 O(n ^ 2))算法来从中删除所有奇数元素。
我的想法是:迭代向量直到第一个奇数元素,然后将它之前的所有内容复制到向量的末尾(调用push_back方法),依此类推,直到我们查看了所有原始元素(除了复制的元素),然后删除所有元素其中只有矢量的尾巴能够存活下来。
我编写了以下代码来实现它:
void RemoveOdd(std::vector<int> *data) {
size_t i = 0, j, start, end;
uint l = (*data).size();
start = 0;
for (i = 0; i < l; ++i)
{
if ((*data)[i] % 2 != 0)
{
end = i;
for (j = start, j < end, ++j)
{
(*data).push_back((*data)[j]);
}
start = i + 1;
}
}
(*data).erase((*data).begin(), i);
}
但它给了我很多错误,我无法修复。我对编程非常陌生,所以期望所有这些都是基本的和愚蠢的。
请帮我修正错误或其他算法实现。任何建议和解释都会非常感激。最好不要使用算法库。
答案 0 :(得分:6)
您可以使用remove-erase idiom。
data.erase(std::remove_if(data.begin(), data.end(),
[](int item) { return item % 2 != 0; }), data.end());
答案 1 :(得分:3)
你真的不需要push_back
任何东西(或者在前面擦除元素,这需要重新定位所有后面的元素)来根据谓词删除元素...尝试理解&#34 ;经典&#34; inplace删除算法(最终通常是std::remove_if
的实现方式):
void RemoveOdd(std::vector<int> & data) {
int rp = 0, wp = 0, sz = data.size();
for(; rp<sz; ++rp) {
if(data[rp] % 2 == 0) {
// if the element is a keeper, write it in the "write pointer" position
data[wp] = data[rp];
// increment so that next good element won't overwrite this
wp++;
}
}
// shrink to include only the good elements
data.resize(wp);
}
rp
是&#34;读&#34;指针 - 它是当前元素的索引; wp
是&#34;写&#34;指针 - 它总是指向我们写下一个&#34;好&#34;的位置。元素,也是&#34;当前长度&#34; &#34;新&#34;向量。每次我们有一个好的元素时,我们将它复制到写入位置并递增写入指针。假设wp <= rp
总是(因为rp
在每次迭代时增加一次,并且每次迭代最多wp
一次),您总是覆盖一个元素本身(因此没有造成伤害),或者已经检查过的元素已被移动到正确的最终位置,或者无论如何都必须丢弃。
此版本使用特定类型(vector<int>
),特定谓词,索引以及&#34;常规&#34; (非移动)赋值,但可以很容易地推广到任何具有前向迭代器的容器(如在std::remove_if
中完成)和erase
。
即使通用标准库算法在大多数情况下运行良好,这仍然是一个重要的算法要记住,通常情况下通用库版本不够充分并且知道基本思想对于实现自己的版本。
答案 2 :(得分:2)
鉴于纯算法实现,您不需要推回元素。在最坏的情况下,您将执行超过n ^ 2的复制。 (所有奇数据)
保留两个指针:一个用于迭代(i),另一个用于放置。迭代所有向量(i ++),如果* data [I]是偶数,则将其写入* data [placement]并递增放置。最后,减少放置的长度,之后的所有元素都是不必要的
remove_if为你做这件事;)
答案 3 :(得分:-1)
void DeleteOdd(std::vector<int> & m_vec) {
int i= 0;
for(i= 0; i< m_vec.size(); ++i) {
if(m_vec[i] & 0x01)
{
m_vec.erase(m_vec.begin()+i);
i--;
}
}
m_vec.resize(i);
}