我已经提出了以下程序来实现它,但它似乎无法工作并进入无限循环。它的工作方式类似于快速排序。
int main()
{
int arr[] = {1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1};
int N = 18;
int *front, *last;
front = arr;
last = arr + N;
while(front <= last)
{
while( (front < last) && (*front == 0) )
front++;
while( (front < last) && (*last == 1) )
last--;
if( front < last)
{
int temp = *front;
*front = *last;
*last = temp;
front ++;
last--;
}
}
for(int i=0;i<N;i++)
printf("%d ",arr[i]);
return 0;
}
答案 0 :(得分:22)
你的意思是阵列只有0
和1
s?
对所有N个元素求和,然后覆盖数组:)
int main() {
int arr[] = {1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1};
int N = sizeof arr / sizeof *arr; /* 18 */
int sum = 0;
int ndx;
for (ndx=0; ndx<N; ndx++) sum += arr[ndx];
for (ndx=0; ndx<N-sum; ndx++) arr[ndx] = 0;
for (ndx=N-sum; ndx<N; ndx++) arr[ndx] = 1;
}
答案 1 :(得分:16)
我在程序中看到至少两个问题:
问题1:
last = arr + N;
不正确。它应该是:
last = arr + N - 1;
,因为
(arr + 0) points to 0th ele
(arr + 1) points to 1st ele
...
(arr + N -1) points to (N-1)th ele..which is the last element.
Problem2:
接下来你的while循环:
while(front <= last)
不正确,应该是:
while(front < last)
在你和前一个和最后一个相等的情况下,你的循环继续但是 此时前面和后面都没有被修改,导致无限循环。
当前面和后面变得相等时,没有必要继续你的阵列 本来可以排序。
答案 2 :(得分:5)
您的算法的基本思想很好,并且可以简化实现:
int a[] = {1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1};
int *begin = a;
int *end = begin + 17;
while (begin < end) {
if (*begin == 0)
begin++;
else if (*end == 1)
end--;
else {
*begin = 0;
*end = 1;
}
}
请注意(begin < end)
是终止循环的更强条件,并且在每次迭代中只执行一次操作(移动指针或交换值),简化了代码并使其更容易理解循环将真正终止。
答案 3 :(得分:4)
你自己太难了!你可以在O(n)中只知道数组n
的大小和元素S
的总和。由于二元数组每个元素只有两种可能性,因此知道一个元素的数量和总大小就足够了。
一旦你知道,只需按顺序输出一个包含S - n
个零和n
个的数组。完成!
另一种不需要先求和并就地工作的方法如下:在索引0处放置一个“写”指针w
,在一个位置放置一个“读”指针r
指数n-1。使用读指针向后迭代,每次遇到0时,在w
处写一个“0”并递增它。当您使用r
到达开头时,请使用w
使用“1”填充数组的其余部分。
答案 4 :(得分:2)
void my_sort(int* arr, int n){
int zero = -1;
for(int i = 0; i < n;i++){
if(arr[i] == 0){
zero++;
swap(arr[zero],arr[i]);
}
}
}
为最后一个第0个索引保留一个数据透视,并保持从左到右交换所有数字,直到到达数组的末尾
答案 5 :(得分:1)
如果你瞄准O(n)忘记所有快速排序(Θ(nlogn)),bubblesorts等。没有经典排序算法实现标准数据集的O(n),你必须利用集合的二进制特性。
int arr[] = {1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1};
int N = 18;
int i,s=0;
for(i=0;i<N;i++) s+=(arr[i]==0);
for(i=0;i<N;i++) arr[i]=!(i<s);
答案 6 :(得分:1)
答案 7 :(得分:1)
int[] arr = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 };
int left = 0;
int right = arr.Length-1;
int first = arr[left];
while (left < right)
{
if (arr[left] == 0 && arr[right] ==1)
{
left++;
right--;
}
else if (arr[left] == 1 && arr[right] == 1)
{
right--;
}
else if (arr[left] == 0 && arr[right] == 0)
{
left++;
}
else
{
arr[left] = 0;
arr[right] = 1;
left++;
right--;
}
}
答案 8 :(得分:1)
一般解决方案(如果它不仅仅是0和1)被称为“按计数排序”。如果您知道数据在某个范围内,则始终可以使用它。例如。你想按照他们的出生日期对一群人进行排序,不包括年份。 你只需要创建一个367(闰年)的数组,该数组中的每个插槽都是一个能够保存数据的(链接)列表。 现在,您扫描数据,从同行的生日日期计算“一年中的某一天”,并将它们附加到已批准的列表中。
答案 9 :(得分:0)
您的代码不会在我的系统上无限循环:
# gcc $CFLAGS -o test test.c
# ./test
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
然而结果是错误的。我看到8次1,但它应该是9次。
有些人指出,总结是一种更简单的方法:
#include <stdio.h>
int main()
{
int i;
int count;
int N = 18;
int arr[] = {1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1};
/* Sum up all elements */
i = 0;
count = 0;
while (i < N) count += arr[i++];
/* Overwrite the array */
i = 0;
count = N - count;
while (i < count) arr[i++] = 0;
while (i < N) arr[i++] = 1;
/* Print result */
for (i = 0; i < N; i++) printf("%d ",arr[i]);
}
答案 10 :(得分:0)
显然另一个问题已经关闭......你的算法完美无缺。我发布的回复maddy的内容dup明显{{3}}这个内容由关闭它的人重定向
int main()
{
int v[] = {1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1}; int *a, *b, i, n;
n = sizeof(v) / sizeof(int);
for (a = v, b = v + n - 1; a < b; ++a) {
if (*a) {
for (; *b; --b) if (a == b) goto end;
*a = 0; *b-- = 1;
}
}
end: for (i = 0; i < n; ++i) printf("%d%s", v[i], (i==n-1?"\n":",")); return 0;
}
将一些线条移动到一起以使其适合页面....几乎相同
答案 11 :(得分:0)
重新发布此处,因为我回复的问题已经结束(此副本重复)。
我很抱歉用Python回答这个问题,但这是我想要做的练习。代码意味着冗长,以输出算法的步骤。当然,只要你小心移动指针,转换为C并不困难。干杯!
# Put zeros on the left, ones on the right in one pass
a = [1,0,1,0,0,1,1,1,0,0,1,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,1]
cl = 0
cr = len(a) - 1
print a
while(True):
if cl + 1 == cr:
print 'last pass; adjacent elements'
if a[cl] == 0:
print 'a[%d] = 0; leave and exit loop' % (cl)
print 'final array:'
print a
break
if a[cl] == 1:
print 'a[%d] = 1; try to swap with a[%d]' % (cl, cr)
if a[cr] == 1:
print 'a[%d] = 1 as well; leave and exit loop' % (cr)
print 'final array:'
print a
break
else:
print 'a[%d] and a[%d] swapped; leave and exit loop' % (cl, cr)
a[cl] = 0
a[cr] = 1
print 'final array:'
print a
break
if a[cl] == 0:
print 'a[%d] = 0; leave and move on to a[%d]' % (cl,cl+1)
cl += 1
continue
else:
print 'a[%d] = 1 move to the right' % (cl)
while(True):
if a[cr] == 1:
print 'a[%d] cannot be moved to a[%d], try a[%d]' % (cl, cr, cr-1)
cr -= 1
continue
else:
print 'a[%d] swapped with a[%d]' % (cl, cr)
a[cr] = 1
a[cl] = 0
cr -= 1
cl += 1
print 'next up: a[%d]; right side blocked up to %d' % (cl,cr)
break
if (cl + 1) == cr:
break
示例输出:
[1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1]
a[0] = 1 move to the right
a[0] cannot be moved to a[26], try a[25]
a[0] swapped with a[25]
next up: a[1]; right side blocked up to 24
a[1] = 0; leave and move on to a[2]
a[2] = 1 move to the right
a[2] cannot be moved to a[24], try a[23]
a[2] swapped with a[23]
next up: a[3]; right side blocked up to 22
a[3] = 0; leave and move on to a[4]
a[4] = 0; leave and move on to a[5]
a[5] = 1 move to the right
a[5] swapped with a[22]
next up: a[6]; right side blocked up to 21
a[6] = 1 move to the right
a[6] cannot be moved to a[21], try a[20]
a[6] cannot be moved to a[20], try a[19]
a[6] swapped with a[19]
next up: a[7]; right side blocked up to 18
a[7] = 1 move to the right
a[7] swapped with a[18]
next up: a[8]; right side blocked up to 17
a[8] = 0; leave and move on to a[9]
a[9] = 0; leave and move on to a[10]
a[10] = 1 move to the right
a[10] cannot be moved to a[17], try a[16]
a[10] cannot be moved to a[16], try a[15]
a[10] swapped with a[15]
next up: a[11]; right side blocked up to 14
a[11] = 0; leave and move on to a[12]
a[12] = 0; leave and move on to a[13]
last pass; adjacent elements
a[13] = 1; try to swap with a[14]
a[13] and a[14] swapped; leave and exit loop
final array:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
答案 12 :(得分:0)
这是一个简单的答案:)
int main()
{
int a[]={1,0,1,1,1,0,1,0,1},size=9,end_value,index1,index2=-1;
end_value=a[size-1];
for(index1=0;index1 < size-1;index1++)
{
if(a[index1]==end_value )
{
index2++;
a[index2]=!a[index2];
a[index1]=!a[index1];
}
}
index2++;
a[index2]=!a[index2];
a[index1]=!a[index1];
}
答案 13 :(得分:0)
这可以通过简单的二进制counting sort:
来完成#include <stdio.h>
int main()
{
int N = 18, zeros=0, i;
int arr[] = {1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1}, *ptr, *last;
ptr = arr;
last = arr + N - 1;
while (ptr != last)
{
if (!*ptr) zeros++;
ptr++;
}
for (i = 0; i < zeros; i++) arr[i] = 0;
for (; i < N; i++) arr[i] = 1;
for (i = 0; i < N; i++)
printf("%d ", arr[i]);
putchar('\n');
return 0;
}
答案 14 :(得分:0)
这应该可以正常工作。只有一个循环才能完成这项任务。
int arr[]={0,0,0,1,0,1,0,1,0};
int lastz=7,i=0,temp,n;
n=9;
while(i<n){
if(arr[i]==0 && i<lastz){
lastz=i;
} else if(arr[i]==1 && lastz<i){
temp=arr[lastz];
arr[lastz]=arr[i];
arr[i]=temp;
lastz++;
}
i++;
}
答案 15 :(得分:0)
这是C实现,它将在O(n)时间内提供解决方案。
/*
C program to sort a binary array in one pass
Input: 0 1 0 1 1 0
OutPut: 0 0 0 1 1 1
*/
#include<stdio.h>
void segregate0and1(int*, int);
int main()
{
int a[] = {0, 1, 0, 1, 1, 0};
int array_length = sizeof(a)/sizeof(a[0]);
segregate0and1(a, array_length);
printf("Array after segregation: ");
for (int i = 0; i < array_length; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
void segregate0and1(int a[], int array_length)
{
int left = 0, right = array_length-1;
while (left < right)
{
/* Increment left index while we see 0 at left */
while (a[left] == 0 && left < right)
left++;
/* Decrement right index while we see 1 at right */
while (a[right] == 1 && left < right)
right--;
/* If left is smaller than right then there is a 1 at left
and a 0 at right. Exchange a[left] and a[right]*/
if (left < right)
{
a[left] = 0;
a[right] = 1;
}
}
}