2011-03-10 72 views
4

我有一个包含0 s和1 s的混合物的阵列。我想重新排列数组的内容,以便数组中的偶数位置包含0,并且奇数位置尽可能包含1,但须遵守0s和1s的数量不变的限制。这意味着如果0 s的数量超过了1 s的数量,反之亦然,那么在重新排列的数组的末尾会有一个块,由全部0 s或全部1 s组成。我怎样才能一次完成此操作,修改阵列?双色抖动

例如:

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} 
+2

这里也真不是个问题...(按Ctrl + F查找你的问题没有 “?” 字符)通常我们(在Stack Overflow)要求您显示您什么尝试,并问问你有什么问题。请参阅:http://tinyurl.com/so-hints – Crisfole 2011-03-10 17:46:36

+2

我不明白“让他们在哪里”的要求。在您的输入中,1的数量超过了0的数量。那么,你究竟是什么离开了“他们在哪里”? – AnT 2011-03-10 23:32:26

+1

你的例子有更多的1比0,但它不会离开他们所在的一切。 – 2011-03-10 23:42:26

回答

4

你可以使用这个标准的双色排序算法;只需编辑数组引用即可将对数组前半部分的访问映射到实际数组中的偶数元素,并将数组的后半部分访问到实际数组中的奇数元素(向后)。基本上,a[i]变(假设size甚至):

a[i < size/2 ? i * 2 : (size - i) * 2 - 1] 
+0

你能给我一个双色排序算法的参考吗?我还没有发现它与谷歌。 – xanatos 2011-03-10 18:23:16

+0

@xanatos:见http://en.wikipedia.org/wiki/Quicksort#Complex_version;在你的情况下,主键是1,你在开始的时候把事物放在比它小的地方,而事物大于或等于它的结尾。 – 2011-03-10 19:28:22

2

我不认为它可以在1个行程进行,除非“离开他们,他们是”意味着“不,他们到底怎么做向上”。

这是我尝试用两道:)

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; 
    } 
    } 
} 
+0

+1同意。如果必须进行“排序”,直到第一遍结束才能确定,因此无法在第一次迭代中执行“排序”。在一次迭代中完成它的唯一方法是使用第二个数组。 – ruslik 2011-03-11 00:57:31

2

遍历数组,维持3个变量的不变量和数组:

  • 一切之前pos已排序。
  • color是应放置在pos处的元素的颜色。
  • posnext之间的所有内容都具有相同的颜色。
  • 该数组本身是一个排列组合。

无论如何,它似乎工作。

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 
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} 
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)

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; 
     } 
    } 
} 
1

这可以单程完成。

这是另一种使用单程的解决方案。这个想法是保持两个索引pos_0pos_1,它们保存下一个01要放置在阵列中的位置。将使用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; 
      } 
     } 
    } 
} 
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++; 
    } 
    } 
} 
+3

欢迎来到StackOverflow,尽管这段代码看起来很有用,可以帮助别人理解它。 – 2012-12-12 11:54:20

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]); 
}