我有一个包含0
和1
s混合的数组。我想重新排列数组的内容,以便数组中的偶数位置包含0
,奇数位置包含1
,但受限于0
s的数量并且1
没有变化。这意味着如果0
的数量超过1
的数量,反之亦然,那么在重新排列的数组的末尾会有一个块,包括所有 - 0
或全部 - 1
秒。如何在一次通过中修改数组?
例如:
Input: {0,1,1,0,1,0,1,0,1,1,1,0,0,1,0,1,1}
Output: {0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1}
答案 0 :(得分:4)
您可以使用标准的双色排序算法;只需编辑数组引用,将对数组前半部分的访问映射到实际数组中的偶数元素,然后访问数组的后半部分到实际数组中的奇数元素(向后)。基本上,a[i]
变为(假设size
是偶数):
a[i < size/2 ? i * 2 : (size - i) * 2 - 1]
答案 1 :(得分:2)
我不认为它可以一次通过,除非“将它们留在原处”意味着“它们最终会在哪里无关紧要”。
这是我尝试两次传球:)
void zeroone(int *arr, size_t n) {
int *ptr = arr;
size_t nn = n;
int s = 0;
/* if the array has an odd number of elements
** the number of 0's is different then the number of 1's */
if (n % 2) return;
/* 1st pass */
while (nn--) s += *ptr++;
/* if there are as many 0's as 1's */
if (s+s == n) {
/* 2nd pass */
for (nn = 0; nn < n; nn += 2) {
arr[nn] = 0;
arr[nn + 1] = 1;
}
}
}
答案 2 :(得分:2)
循环遍历数组,维护3个变量和数组的不变量:
pos
之前的所有内容都已排序。color
是应放置在pos
。pos
和next
之间的所有内容都具有相同的颜色。无论如何,它似乎有效。
def odd_even_sort(xs):
color = 0
pos = 0
next = pos + 1
while next < len(xs):
if xs[pos] == color:
pos += 1
if pos >= next:
next = pos + 1
color = not color
elif xs[next] == color:
xs[pos], xs[next] = xs[next], xs[pos]
next += 1
pos += 1
color = not color
else:
next += 1
xs = [0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1]
odd_even_sort(xs)
print xs
答案 3 :(得分:2)
int a[10] = {1, 1, 0, 1, 1, 0, 1, 1, 1, 0};
int i;
int count_0 = 0;
int count_1 = 0;
for(i = 0; i < 10; i++)
{
if(a[i] == 0)
{
if(count_1 > 0)
{
if(i % 2 == 0)
{
a[i-2*count_1+1] = 0;
a[i] = 1;
count_1--;
}
else
{
a[i-2*count_1] = 0;
a[i] = 1;
}
}
else
{
if(i % 2 == 0)
count_0++;
}
}
else
{
if(count_0 > 0)
{
if(i % 2 != 0)
{
a[i-2*count_0+1] = 1;
a[i] = 0;
count_0--;
}
else
{
a[i-2*count_0] = 1;
a[i] = 0;
}
}
else
{
if(i % 2 != 0)
count_1++;
}
}
}
答案 4 :(得分:1)
这样做。结果与提议的输出不同,但是等于给出的规则(问题的文本不包括“排序”一词,只是在最后你必须移动所有0
你可以在偶数位置和1
你可以在奇数位置。你不需要“压缩”它们。将它“压缩”起来有点复杂。
static void Main(string[] args)
{
var input = new[] { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1 };
var lastEvenToMove = -1;
var lastOddToMove = -1;
for (int i = 0; i < input.Length; i++)
{
bool needEven = i % 2 == 0;
bool isEven = input[i] == 0;
if (needEven == isEven)
{
continue;
}
if (needEven)
{
if (lastEvenToMove != -1)
{
var old = input[lastEvenToMove];
input[lastEvenToMove] = 1;
input[i] = 0;
lastEvenToMove = old;
}
else
{
input[i] = lastOddToMove;
lastOddToMove = i;
}
}
else
{
if (lastOddToMove != -1)
{
var old = input[lastOddToMove];
input[lastOddToMove] = 0;
input[i] = 1;
lastOddToMove = old;
}
else
{
input[i] = lastEvenToMove;
lastEvenToMove = i;
}
}
}
while (lastEvenToMove != -1)
{
var old = input[lastEvenToMove];
input[lastEvenToMove] = 0;
lastEvenToMove = old;
}
while (lastOddToMove != -1)
{
var old = input[lastOddToMove];
input[lastOddToMove] = 1;
lastOddToMove = old;
}
Console.WriteLine(@"{{{0}}}", String.Join(", ", input.Select(p => p.ToString())));
}
我保留了一堆赔率和一堆需要移动的偶数元素,当我需要奇数/偶数时我会使用它们。两个堆栈保留在输入数组中,因此没有额外的空间(两个堆栈的两个“头”除外,这是两个额外的整数)。我认为最坏的情况是O(1.5n)
时间(例如,所有元素都是1
,一半的元素被“放入”堆栈然后需要重置,因为没有空的空间)和O(1)
代表空间。
输出:
{0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1}
答案 5 :(得分:1)
#include<iostream>
using namespace std;
//////////////////////////////////////////
int a[]={1,1,0,1,0,1,1,1,0,1,0,1,0,0,0,0,1,1,1,1,0,0} ;
int main()
{
int zero = 0, one = 1;
int n = sizeof(a)/sizeof(*a);
int i = 0;
while ( zero < n && one < n)
{
if(a[zero] != 0 && a[one] != 1)
{
swap(a[zero],a[one]);
}
if(a[zero] == 0)
{
zero=zero+2;
}
if(a[one] == 1)
{
one=one+2;
}
}
}
答案 6 :(得分:1)
这可以单程完成。
这是另一种使用单次传递的解决方案。我们的想法是保留两个索引pos_0
和pos_1
,这两个索引保存下一个0
或1
放置在数组中的位置。 i
将用于遍历数组。
//
//array a[] and length are members of the class AlternateZeroAndOne
//
void AlternateZeroAndOne::sortArray()
{
int pos_0 = 0;
int pos_1 = 1;
for (int i=0; i<length; ++i)
{
//
// We have been waiting for a zero to be placed at the correct location.
//
if (pos_0 < pos_1)
{
if (a[i] == 0)
{
swap(pos_0, i);
pos_0+=2;
//
// If we had a 1 already at the right place, increment pos_1.
//
if (a[pos_1] == 1)
pos_1+=2;
}
}
//
// We have been waiting for a one to be placed at the correct location.
//
else
{
if (a[i] == 1)
{
swap(pos_1, i);
pos_1 += 2;
//
// If we had a 0 already at the right place, increment pos_0.
//
if (a[pos_0] == 0)
pos_0+=2;
}
}
}
}
答案 7 :(得分:0)
因为它只有1和0,你可以只计算它们的数量差异,排序很容易:
int size = arr.length();
int diff = 0, i;
for(i = 0; i < size; i++) // put 0 in odd places and 1 in even and count the extra changes
if(i % 2 == 0)
if(arr[i] == 1){
arr[i] = 0;
diff++;
}
else
if(arr[i] == 0){
arr[i] = 1;
diff--;
}
for(i--; diff != 0; i--){ //make the tail
if(diff > 0) //if we owe 1's put in on 0's
if(arr[i] == 0){
arr[i] = 1;
diff--;
}
if(diff < 0) //if we owe 0's put in on 1's
if(arr[i] == 1){
arr[i] = 0;
diff++;
}
}
很容易理解为什么它是正确的所以我不会解释。时间复杂度:O(arr.length())或O(n)
答案 8 :(得分:0)
#include<stdio.h>
void swap(int *p,int *q)
{
int temp=*p;
*p=*q;
*q=temp;
}
int main()
{
int a[]={0,1,1,0,1,0,1,0,1,1,1,0,0,1,0,1,1};
int z=0,o=1,i;
while(z<17&&o<17)
{
if(a[z]==1&&a[o]==0)
swap(&a[z],&a[o]);
if(a[z]==0)
z+=2;
if(a[o]==1)
o+=2;
}
if(z<17&&a[z]==1)
{
while(z<15)
{
swap(&a[z],&a[z+2]);
z+=2;
}
}
if(o<17&&a[o]==0)
{
while(o<15)
{
swap(&a[o],&a[o+2]);
o+=2;
}
}
for(i=0;i<17;i++)
printf("%d ",a[i]);
}