On Jul 3, 2:01 pm, jalaj jaiswal <jalaj.jaiswa...@gmail.com> wrote:
>  Let an array contain values : a1,a2,... ,an, b1,b2,..., bn Write a program
> to change this array to : a1,b1,a2,b2, ..., an,bn in O(n) time and in O(1)
> space.
>
> i did it by shiftng of elements which is not much efficient.. any better way
> ?

This is a tricky problem.  Here is link to a very elegant solution.
It uses some basic number theory to find permutation cycles.
http://arxiv.org/pdf/0805.1598v1

Here is code that's tested for n up to 1,000,000.  Not this actually
produces b1,a1,b2,a2, ....  But you could easily make a final pass to
swap pairs.

#include <stdio.h>

void print(char *msg, int *a, int i, int j)
{
  printf("%s: ", msg);
  while (i < j)
    printf(" %d", a[i++]);
  printf("\n");
}

// Swap a[i] and a[j].
void swap(int *a, int i, int j)
{
  int t = a[i];  a[i] = a[j]; a[j] = t;
}

// Reverse a[i..j)
void reverse(int *a, int i, int j)
{
  while (i < j) swap(a, i++, --j);
}

// Rotate a[i..j) left by m positions.
void rotate_left(int *a, int i, int j, int m)
{
  reverse(a, i, i + m);
  reverse(a, i + m, j);
  reverse(a, i, j);
}

// Rotate a[i..j) right by m positions.
void rotate_right(int *a, int i, int j, int m)
{
  rotate_left(a, i, j, j - i - m);
}

// Find index mapping: Shuffle(a[i]) = a[imap(i)]
int imap(int i, int n)
{
  return (i & 1) ? i / 2 : i / 2 + n;
}

// Shuffle a[0..2m) where 2m = 3^k - 1
void shuffle3k(int *a, int m, int k)
{
  int i, p0, p, q, t;

  for (i = 0, p0 = 0; i < k; i++, p0 = (3 * p0) + 2) {
    t = a[p0];
    for (p = p0, q = imap(p, m); q != p0; p = q, q = imap(q, m)) {
      a[p] = a[q];
    }
    a[p] = t;
  }
}

// Find k and m such that 2m = 3^k - 1 <= 2n < 3^(k+1) - 1
void get_m(int n, int *k_ret, int *m_ret)
{
  int k, p, q;
  for (k = -1, p = 0, q = 1; q - 1 <= 2 * n; k++, p = q, q *= 3)
    /* skip */ ;
  *k_ret = k;
  *m_ret = (p - 1) / 2;
}

// Do a perfect shuffle on a, which has 2n elements.
void shuffle(int *a, int n)
{
  int k, m, i;

  i = 0;
  do {
    get_m(n, &k, &m);
    rotate_right(a, i + m, i + m + n, m);
    shuffle3k(a + i, m, k);
    i += 2 * m;
    n -= m;
  } while (n > 0);
}

int main(void)
{
  int a[1000000];
  int i, n;

  for (n = 1; n <= sizeof a / sizeof a[0] / 2; n++) {
    if (n % 1000 == 0) fprintf(stderr, ".");
    for (i = 0; i < n; i++) {
      a[i] = i + 1;
      a[i + n] = i + 1 + 1000;
    }
    //print("initial", a, 0, 2 * n);
    shuffle(a, n);
    for (i = 0; i < n; i++) {
      if (a[2 * i] != i + 1 + 1000 || a[2 * i + 1] != i + 1) {
        print("error", a, 0, 2 * n);
        return 1;
      }
    }
    //print("result", a, 0, 2 * n);
  }
  return 0;
}

-- 
You received this message because you are subscribed to the Google Groups 
"Algorithm Geeks" group.
To post to this group, send email to algoge...@googlegroups.com.
To unsubscribe from this group, send email to 
algogeeks+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/algogeeks?hl=en.

Reply via email to