"良好的C ++解决方案将所有零带到数组的后面"面试挑战

时间:2014-11-18 20:44:33

标签: c++ algorithm

我接受了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);

还有什么其他好的答案?

3 个答案:

答案 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));

Live Example

基本上,如果您需要将满足条件的项目移动到容器的“一侧”,那么分区算法函数应该在要选择的解决方案列表中高位(如果不是 使用的解决方案)。

答案 1 :(得分:2)

排序的方法是O(N * Log 2 N)。有一个线性解决方案是这样的:

  • 设置两个指针 - readPtrwritePtr,最初指向数组的开头
  • 创建一个循环,将数组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);