我试图编写快速而最酷的解决方案来解决将所有问题都放在一个零和一组数字前面的问题。
我写了这个:
void zeros_to_front(char * c, int n)
{
char * lastPtr(c);
for (char * thisCharPtr(c), * endCharPtr(c+n+1); thisCharPtr != endCharPtr; ++thisCharPtr)
{
if (*thisCharPtr == '1')
{
*lastPtr = '1';
*thisCharPtr = '0';
++lastPtr;
}
}
}
int main()
{
char thisArray[] = {'0', '0', '1', '0', '1', '1', '1'};
int len = sizeof(thisArray)/sizeof(char);
zeros_to_front(thisArray, len);
for (int i = 0; i < len; ++i)
std::cout << thisArray[i] << " ";
return 0;
}
几个问题:
有没有办法简化
*lastIdxPtr = '1';
++lastIdxPtr;
分为1行?
答案 0 :(得分:3)
最快的方法是两次通过计数方法。为什么?因为它消除了内环中对条件的需要,这是昂贵的。这是代码:
void zerosToFront(char* c, size_t n) {
size_t oneCount = 0, i;
for(i = 0; i < n; i++) oneCount += c[i];
for(i = 0; i < n - oneCount; i++) c[i] = 0;
for( ; i < n; i++) c[i] = 1;
}
答案 1 :(得分:3)
此版本采用与cmasters相同的形式,但可能更快,具体取决于您的标准库实现。我知道Visual C ++会将这些std::fill
调用中的每一个调成memset()
。
void zero_to_front(char* c, int n)
{
size_t ones = std::count(c, c + n, '1');
std::fill(c, c + ones, '1');
std::fill(c + ones, c + n, '0');
}
答案 2 :(得分:2)
这个问题有很多解决方案。我将从非常简单的开始。
<强>解决方法1:强> 计算数组中的1的数量,并用数字填充数组的前面元素,并用零填充数组的其余部分。以下代码执行了 -
void zero_to_front(char* c, int n)
{
int count = 0;
for(int i=0; i<n; i++)
if(c[i] == 1) count++;
for(int i=0; i<n; i++)
if(i<count) c[i]=1;
else c[i] = 0
}
时间复杂度为: O(n)
解决方案2:每次在数组中找到0时,在数组中的以下位置查找1并交换它。以下代码就是这样做的。
void zero_to_front(int*c, int n){
int one_pos = -1;
for (int i = 0; i < n; i++) {
if (c[i] == 0) {
if(one_pos == -1)
one_pos = i+1;
//Find the position of first one
while (one_pos < n && c[one_pos] != 1 )
one_pos++;
//swap(c[i], c[one_pos]);
int temp = c[i];
c[i] = c[one_pos];
c[one_pos] = temp;
}
}
}
时间复杂度为: O(n)
<强> Solution3:强> 按相反顺序对数组进行排序。 时间复杂度为: O(nlogn)
答案 3 :(得分:1)
此解决方案将需要在数组和空间O(n)中传递1次。 最终结果存储在数组结果
中 void cal(int *data , int* result , int n) {
int index = n - 1;
for(int i = 0; i < n; i++){
if(data[i] == 1){
result[index--] = 1;
}
}
}