陈利人:#Facebook面试题#这是一个编程题,动手做做才会有体会。给一个数组和一个值,从数组中删除这个指定的值的所有出现,
并且返回新的数组的长度。size_t remove_elem(T* array, size_t len, T elem) {}。
解题:
首先可以想到的是,用额外用一个数组。遇到不同的元素,就把此元素拷至额外的数组中。
实际上,很快就可以发现,用额外的数组与用当前这个数组,效果完全一样。
所以f = from;也就是直接指向当前数组的开头。
#include <iostream>
#include <iterator>
using namespace std;
template<class iterator, class T>
size_t xremove(iterator from, iterator to, const T &v) {
if (from >= to) return -1;
iterator b = from - 1, e = to, f = from;
while(++b != e)
if (*b != v) *f++ = *b;
return f - from;
}
template<class T>
size_t xremove(T *a, const int n, const T &v) {
if (!a || n <= 0) return -1;
return xremove(a, a + n, v);
}
int main(void) {
int array[] = {1,2,3,2,2,2,2,2,2,2,2,2,};
int len = sizeof(array)/sizeof(*array);
int length = xremove(array, len, 4);
copy(array, array + length, ostream_iterator<int>(cout, " "));
return 0;
}
可能现在,你觉得已经写好了。可以是很快又会发现。当数组中没有你想要删除的元素的时候,会出现重复拷贝的情况。也就是
会在原地拷贝。特别是当T类型是自定义类型。并且没有自己实现operator =运算符的时候,代价会比较高。
不要告诉我很多operator =的时候,都有
if (this != &a) { }才拷贝。当你没有写operator =的时候,系统会自动给你一个。谁知道那个是怎么工作的。
那么再把代码更改一下。由于考虑到iterator可能没有减法或者大于操作。那么只能再把代码再更改一下。
#include <iostream>
#include <iterator>
using namespace std;
template<class iterator, class T>
size_t xremove(iterator from, iterator to, const T &v) {
if (from == to) return -1;
iterator b = from, e = to, f = from;
do {
if (*b != v) {
if (f < b) *f = *b;
++f;
}
} while (++b != e);
return f - from;
}
template<class T>
size_t xremove(T *a, const int n, const T &v) {
if (!a || n <= 0) return -1;
return xremove(a, a + n, v);
}
int main(void) {
int array[] = {1,2,3,2,2,2,2,2,2,2,2,2,};
int len = sizeof(array)/sizeof(*array);
int length = xremove(array, len, 4);
copy(array, array + length, ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}