我接受了Jr.开发工作的采访,他让我写了一个程序,它采取一系列的整数并将零推到后面。以下是约束(他在开始时并没有告诉我......正如在编程访谈中经常发生的那样,我在解决问题的过程中学会了问题的限制):
设定:
int arr[] = {0, -2, 4, 0, 19, 69};
/* Transform arr to {-2, 4, 19, 69, 0, 0} or {69, 4, -2, 19, 0, 0}
or anything that pushes all the nonzeros to the back and keeps
all the nonzeros in front */
我的回答:
bool f (int a, int b) {return a == 0;}
std::sort(arr, arr+sizeof(arr)/sizeof(int), f);
还有什么其他好的答案?
答案 0 :(得分:13)
也许面试官正在寻找这个答案:
#include <algorithm>
//...
std::partition(std::begin(arr), std::end(arr), [](int n) { return n != 0; });
如果需要保留订单,则应使用std::stable_partition
:
#include <algorithm>
//...
std::stable_partition(std::begin(arr), std::end(arr), [](int n) { return n != 0; });
对于预C ++ 11:
#include <functional>
#include <algorithm>
//...
std::partition(arr, arr + sizeof(arr)/sizeof(int),
std::bind1st(std::not_equal_to<int>(), 0));
基本上,如果您需要将满足条件的项目移动到容器的“一侧”,那么分区算法函数应该在要选择的解决方案列表中高位(如果不是 使用的解决方案)。
答案 1 :(得分:2)
排序的方法是O(N * Log 2 N)。有一个线性解决方案是这样的:
readPtr
和writePtr
,最初指向数组的开头readPtr
向上移动到最后。如果*readPtr
不为零,请复制到*writePtr
,然后推进两个指针;否则,仅提前readPtr
。readPtr
位于数组的末尾,将writePtr
移动到数组的末尾,同时将零写入其余元素。答案 2 :(得分:0)
这是O(n)所以它可能是他正在寻找的东西:
auto arrBegin = begin(arr);
const auto arrEnd = end(arr);
for(int i = 0; arrBegin < arrEnd - i; ++arrBegin){
if(*arrBegin == 0){
i++;
*arrBegin = *(arrEnd - i);
}
}
std::fill(arrBegin, arrEnd, 0);