11

Given an array with positive and negative integers, move all the odd indexed elements to the left and even indexed elements to the right.

The difficult part of the problem is to do it in-place while maintaining the order.

e.g.

7, 5, 6, 3, 8, 4, 2, 1

The output should be:

5, 3, 4, 1, 7, 6, 8, 2

If the order didn't matter, we could have been used partition() algorithm of quick sort.

How to do it in O( N )?

Green goblin
  • 9,898
  • 13
  • 71
  • 100
  • 1
    O(n) space+time is trivial using two lists. I assume you are looking for O(1) space? – amit Sep 09 '12 at 11:33
  • 2
    @amit, yes. In-place means O(1) space. – Green goblin Sep 09 '12 at 11:34
  • 3
    This paper describes O(N) in-place algorithm: http://arxiv.org/abs/0805.1598 – Evgeny Kluev Sep 09 '12 at 11:42
  • Why did the 7 move to the right? Should odd numbers on the left remain on the left? What do you intend for the output order? This question is not at all clear. – Adrian McCarthy Oct 10 '12 at 17:38
  • 2
    @AdrianMcCarthy: the question is not about odd/even numbers, but about odd/even-positioned elements. 7 is at even position, so it goes to the right. The problem of rearranging odd/even numbers is discussed in the comments. – Evgeny Kluev Oct 10 '12 at 18:36
  • @AdrianMcCarthy, the title clearly says: Move all odd positioned element to left half and even positioned to right half in-place. What is not clear in this title? – Green goblin Oct 11 '12 at 05:20

6 Answers6

7
  1. Get largest sub-array having size 3k+1
  2. Apply cycle leader algorithm to the parts of this sub-array, starting from positions 1, 3, 9, ... 3k-1: move element to its proper position in sub-array (even-indexed elements to the left of sub-array, odd-indexed - to the right), the replaced element should be also moved to its proper position, etc. until this procedure comes back to the starting position. This paper gives number-theoretic explanation why such selection of starting positions shuffles sub-array to the correct order.
  3. Process the remaining parts of the array recursively, using steps 1 and 2.
  4. Now we only need to join the reordered parts together. Start with the smaller sub-arrays at the end of the whole array. To exchange sub-array halves, use reverse algorithm: reverse(reverse(a), reverse(b)); or, for sub-array halves of equal size, use pair-wise swaps.
  5. Now all even-positioned elements are on the left. To get them on the right, as required, exchange elements i and i+N/2 for all i = 0 .. N/2-1.

Algorithm is in-place, time complexity is O(N).

Example:

0 1 2 3 4  5 6 7 8 9   10 11 (the original array)
0 1 2 3 4  5 6 7 8 9 # 10 11 (split to sub-arrays)
0 2 4 3 8  1 6 5 7 9 # 10 11 (first cycle leader iteration, starting with 1)
0 2 4 6 8  1 3 5 7 9 # 10 11 (second cycle leader iteration, starting with 3)
0 2 4 6 8  9 7 5 3 1 # 10 11(2nd half of 1st part& 1st half of 2nd part reversed)
0 2 4 6 8 10 1 3 5 7    9 11 (both halves reversed together)

Variation of this algorithm, that does not need step 5:

  • On step 1, get largest sub-array having size 3k-1.
  • On step 2, move even-indexed elements to the right of sub-array, odd-indexed - to the left. Use starting positions 0, 2, 8, ... 3k-1-1 for cycle-leader algorithm.

Here is different O(N log N) in-place algorithm, which does not need number-theoretic proofs:

  1. Reinterpret your array as a sequence of single-element 2*2 matrices, transpose these matrices.
  2. Reinterpret the result as a sequence of two-element 2*2 matrices and transpose them.
  3. Continue while matrices size is less than the array size.
  4. Now we only need to join the reordered parts together (exactly as in previous algorithm).
  5. Exchange elements of left and right halves of the array (exactly as in previous algorithm).

Example:

0  1   2 3   4 5   6 7  (the original array)
[0 2] [1 3] [4 6] [5 7] (first transposition)
[0 2] [4 6] [1 3] [5 7] (second transposition)

This problem is just a special case of the In-place matrix transposition.

Evgeny Kluev
  • 24,287
  • 7
  • 55
  • 98
  • Can you please explain how `0 1 2 3 4 5 6 7` transforms to `0 2 4 3 1 5 6 7` after the first cycle leader iteration? – SexyBeast Oct 07 '12 at 20:17
  • @Cupidvogel: 1 goes to its proper place and replaces 4. Then 4 replaces 2. Then 2 goes to the vacant place, previously occupied by 1. All other elements remain in their places. – Evgeny Kluev Oct 07 '12 at 20:22
  • I just noted that the original array needs the transformations: `0->4,4->6,6->7,7->3,3->1,1->0` and '2->5, 5->2'. As per the paper you suggested, any new permutation is a disjoint set of such cyclic leader rotations. Where does your steps 2-4 fit in? And secondly, is there any guarantee that these rotations won't go for a fairly long time (here it is only 6 and 2 for the 2 sets) so that it no longer remains linear? – SexyBeast Oct 08 '12 at 08:30
  • @Cupidvogel: algorithm should move even-positioned elements to the left (which means we need additional block-exchange at the end to satisfy requirements of this question). Also algorithm works only for sizes 3^k - 1, that's why steps 3..4 are needed. Rotations won't go for a fairly long time because each element is moved exactly once and we stop as soon as we get back to starting position. – Evgeny Kluev Oct 08 '12 at 11:08
  • 2 questions. I just noted that even for arrays whose length is not of the form `3^k-1`, only step 1 suffices. For example, in the length 10 array '4,7,2,9,8,5,1,3,6,5`, to convert it into the array `7 9 5 3 5 4 2 8 1 6`, only 1 cycle is required: `0->5,5->2,2->6,6->8,8->9,9->4,4->7,7->3,3->1 & 1->0`, as summarized by `i -> L/2 + i/2` when `i%2 == 0`, else `i -> i/2`. Steps 3-4 are not required here. And for the given array in question, two sets of disjoint cycles are required. So when does only 1 cycle suffice, and when more than 1 is needed? And if more than 1 is needed, how to know that? – SexyBeast Oct 08 '12 at 14:16
  • @Cupidvogel: For length not of the form `3^k-1` there is no way to know how many cycles we have and where are these cycles, no mathematical proof exists for this case (or at least I don't know one). If you know array length in-advance, you can pre-calculate number of cycles and all starting points, and use them in a fixed-length algorithm. – Evgeny Kluev Oct 08 '12 at 14:33
  • Oh, so you are saying that the need for only one cycle is my 10-element array is a coincidence, it is in general unpredictable? But why 2 cycles are needed for the given array even though it's length is 8 (`3^2-1`)? – SexyBeast Oct 08 '12 at 14:35
  • @Cupidvogel: Yes, it's just coincidence. As for `3^k-1` lengths, there are always `k` cycles; see proof in the paper. – Evgeny Kluev Oct 08 '12 at 14:38
  • Right. But how to find the K-cycles? – SexyBeast Oct 08 '12 at 14:40
  • But the 2 cycles start from 0 and 2 for the given question. One cycle runs as `0->4->6->7->3->1->0` and the other as `2->5->2`. – SexyBeast Oct 08 '12 at 14:46
  • @Cupidvogel: algorithm from the paper is designed to move even-positioned elements to the first half of the array. I've already answered this 3 hours ago. – Evgeny Kluev Oct 08 '12 at 14:51
  • So what modifications need to be done to the algo so that the reverse can also be done, like moving even positioned elements to the right half, as per the question here? – SexyBeast Oct 08 '12 at 14:55
  • @Cupidvogel: after all sub-arrays are transposed and joined (after steps 1..4 are completed), we just exchange elements i and i+N/2 for all i = 0 .. N/2-1 – Evgeny Kluev Oct 08 '12 at 14:58
  • Okay. Can you tell me whether this kind of algo applies to some other situations too, like there is an array where even and odd numbers are interspersed. We have to shuffle it so that even numbers go to even indexes and odd numbers to odd indexes. Initially the numbers are present in no definite order, even indexes may contain both even and odd numbers, same for odd indexes. Can we do it in-place in `O(N)` time with `O(1)` space? – SexyBeast Oct 08 '12 at 15:05
  • This algorithm can only rearrange elements from even **positions** to 1st half of the array or backwards. It completely ignores element values. If you need to rearrange odd/even numbers to odd/even indexes, this algorithm may be used as part of the solution. Actually similar question you asked yesterday, and every answer I gave to it may be used to solve this, in particular, the last one, with in-place radix sort. – Evgeny Kluev Oct 08 '12 at 15:15
  • How can in-place radix sort put even numbers in even indexes and odd numbers in odd-places? – SexyBeast Oct 08 '12 at 15:19
  • @Cupidvogel: If key is a single least significant bit, it can put even numbers to the first half of the array, and (reversed) algorithm from this question can rearrange them to even indexes. – Evgeny Kluev Oct 08 '12 at 15:22
  • How can radix sort put even numbers in the first half of the array? – SexyBeast Oct 08 '12 at 15:26
  • Didn't understand **If key is a single least significant bit, it can put even numbers to the first half of the array**. Can you please provide some pseudo-code? I have never imagined radix-sort doing anything other than sorting, so I can't really envision it. – SexyBeast Oct 08 '12 at 15:41
  • @Cupidvogel: Here's the example: 75638421; after extracting key bits: 11010001; sort them with stable radix sort or any other stable algorithm: 00001111; while sorting, "value" part of each element is moved together with key: 68427531. – Evgeny Kluev Oct 08 '12 at 15:50
  • But again, this is possible only when the number of elements is of the form `3^k-1`, right? And secondly, can you elaborate a bit more in reversing the left-out subarray, combining it with the 2nd half of the main array, etc? – SexyBeast Oct 08 '12 at 16:05
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/17710/discussion-between-evgeny-kluev-and-cupidvogel) – Evgeny Kluev Oct 08 '12 at 16:13
  • @ Evgeny Kluev, What if the array size is of the form 3^k - 1? Suppose the array is given by 0 1 2 3 4 5 6 7. After first cycle leader iteration, starting with 1, it becomes 0 2 4 3 1 5 6 7 . AFter second cycle leader iteration, starting with 3, it becomes 0 2 4 6 1 5 3 7. What to do next? There is no split sub-arrays to reverse. The answer should be 0 2 4 6 1 3 5 7 – Green goblin Oct 09 '12 at 08:20
  • @Aashish: second cycle leader iteration moves 3 to the place of 5 (because its proper position is 5), 5 replaces 6, and 6 comes to unoccupied place of 3. As a result we have 02461357. We'll never have 0 2 4 6 1 5 3 7. – Evgeny Kluev Oct 09 '12 at 10:06
  • @ Evgeny Kluev, thanks I got it. Can you please check your algorithm for the below input? It doesn't seem to be working. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 – Green goblin Oct 10 '12 at 04:42
  • @Aashish: On the contrary, this is very simple input for this algorithm. Here you have 2 sub-arrays, both of size 8. How to transpose arrays of this size shows the example in my answer. The result is 0 2 4 6 1 3 5 7 8 10 12 14 9 11 13 15. Now you exchange 2 middle blocks of 4 elements each (this may be done with simple pairwise element exchange), and finally exchange 1st and 2nd halves of the array to get odd elements first. – Evgeny Kluev Oct 10 '12 at 09:46
  • @ Evgeny Kluev, Can my input be solved by the first approach? As said, i am interested in O( N ) algorithm? Thanks. – Green goblin Oct 10 '12 at 10:01
  • @Aashish: Yes. My previous comment is about the first approach. Blocks of size 8 are exactly the largest sub-arrays having size 3^k-1. – Evgeny Kluev Oct 10 '12 at 10:07
  • @ Evgeny Kluev,After first cycle leader iteration, starting with 1, 0 2 4 3 8 5 6 7 1 9 10 11 12 13 14 15 After second cycle leader iteration, starting with 3, 0 2 4 6 8 5 12 7 1 3 10 11 9 13 14 15 Now, after reversing second half of first part and first half of second part 0 2 4 6 7 12 5 8 11 10 3 1 9 13 14 15. Now, reversing both parts together: 0 2 4 6 1 3 10 11 8 5 12 7 9 13 14 15. I don't know where i have mistaken because the final result i got is wrong. – Green goblin Oct 10 '12 at 10:14
  • @Aashish: please re-read step 1 of the algorithm. You cannot apply cycle leader algorithm to array of any size. You have to split it to sub-arrays of size 3^k-1, transpose each of them, then merge. – Evgeny Kluev Oct 10 '12 at 10:18
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/17807/discussion-between-aashish-and-evgeny-kluev) – Green goblin Oct 10 '12 at 11:01
  • @ Evgeny Kluev, I have observed that the problem arises with size 24, i.e. it is failing for all the cases where size of array is greater than 22. i.e. starting from array, 0 1 2....... 23, it fails for all the cases. So, the algorithm works only for arrays where size <= 22? How to make it work for array of large size also? – Green goblin Oct 10 '12 at 12:55
  • @Aashish: I've just found a bug in the algorithm. After fixing it, array of size 26 is transposed perfectly. Now I'm thinking how to fix the answer. – Evgeny Kluev Oct 10 '12 at 13:07
  • @Aashish: bug was in formula for determining sub-array sizes, now fixed. Thanks for finding it. – Evgeny Kluev Oct 10 '12 at 13:28
  • @Aashish: also pay attention to step 3 of the algorithm. You have to split sub-arrays of size 3^k+1 recursively. There may be more than two such sub-arrays. So your implementation is not correct. – Evgeny Kluev Oct 10 '12 at 13:38
  • @EvgenyKluev Deducing of `k` is not O(1) but is O(log(N)), isn't it? – Tomilov Anatoliy May 28 '14 at 07:44
  • @Orient: It depends. If you have any means of computing natural or binary logarithm in O(1) time then deducing of `k` or computing base-3 logarithm may be also done in O(1) time. Otherwise you could do it in O(log log N) time and space using binary exponentiation. Or O(log log N) time and O(1) space using bitwise tricks. – Evgeny Kluev May 28 '14 at 09:17
  • Not clear what to do with `reverse` (4.) if we have, say, at least 3 parts? E.g. array of length 16 = 10 + 4 + 2. – Tomilov Anatoliy Jun 02 '14 at 10:58
  • The subarrays legths is 10 + 4 + 2. On the second step the length of the right side is six (4 + 2)? Further should we `reverse` subarrays of five (10/2) and three (4/2 + 2/2) sizes and then both together? – Tomilov Anatoliy Jun 02 '14 at 11:12
  • That's right. And if I remember correctly, once again, you've implemented it exactly like this (only with rotate instead of reverse). – Evgeny Kluev Jun 02 '14 at 11:16
1

I tried to implement as Evgeny Kluev said, and here is the result:

#pragma once

#include <iterator>
#include <algorithm>
#include <type_traits>
#include <limits>
#include <deque>
#include <utility>

#include <cassert>

template< typename Iterator >
struct perfect_shuffle_permutation
{

    static_assert(std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::random_access_iterator_tag >::value,
                  "!");

    using difference_type = typename std::iterator_traits< Iterator >::difference_type;
    using value_type = typename std::iterator_traits< Iterator >::value_type;

    perfect_shuffle_permutation()
    {
        for (difference_type power3_ = 1; power3_ < std::numeric_limits< difference_type >::max() / 3; power3_ *= 3) {
            powers3_.emplace_back(power3_ + 1);
        }
        powers3_.emplace_back(std::numeric_limits< difference_type >::max());
    }

    void
    forward(Iterator _begin, Iterator _end) const
    {
        return forward(_begin, std::distance(_begin, _end));
    }

    void
    backward(Iterator _begin, Iterator _end) const
    {
        return backward(_begin, std::distance(_begin, _end));
    }

    void
    forward(Iterator _begin, difference_type const _size) const
    {
        assert(0 < _size);
        assert(_size % 2 == 0);
        difference_type const left_size_ = *(std::upper_bound(powers3_.cbegin(), powers3_.cend(), _size) - 1);
        cycle_leader_forward(_begin, left_size_);
        difference_type const rest_ = _size - left_size_;
        if (rest_ != 0) {
            Iterator middle_ = _begin + left_size_;
            forward(middle_, rest_);
            std::rotate(_begin + left_size_ / 2, middle_, middle_ + rest_ / 2);
        }
    }

    void
    backward(Iterator _begin, difference_type const _size) const
    {
        assert(0 < _size);
        assert(_size % 2 == 0);
        difference_type const left_size_ = *(std::upper_bound(powers3_.cbegin(), powers3_.cend(), _size) - 1);
        std::rotate(_begin + left_size_ / 2, _begin + _size / 2, _begin + (_size + left_size_) / 2);
        cycle_leader_backward(_begin, left_size_);
        difference_type const rest_ = _size - left_size_;
        if (rest_ != 0) {
            Iterator middle_ = _begin + left_size_;
            backward(middle_, rest_);
        }
    }

private :

    void
    cycle_leader_forward(Iterator _begin, difference_type const _size) const
    {
        for (difference_type leader_ = 1; leader_ != _size - 1; leader_ *= 3) {
            permutation_forward permutation_(leader_, _size);
            Iterator current_ = _begin + leader_;
            value_type first_ = std::move(*current_);
            while (++permutation_) {
                assert(permutation_ < _size);
                Iterator next_ = _begin + permutation_;
                *current_ = std::move(*next_);
                current_ = next_;
            }
            *current_ = std::move(first_);
        }
    }

    void
    cycle_leader_backward(Iterator _begin, difference_type const _size) const
    {
        for (difference_type leader_ = 1; leader_ != _size - 1; leader_ *= 3) {
            permutation_backward permutation_(leader_, _size);
            Iterator current_ = _begin + leader_;
            value_type first_ = std::move(*current_);
            while (++permutation_) {
                assert(permutation_ < _size);
                Iterator next_ = _begin + permutation_;
                *current_ = std::move(*next_);
                current_ = next_;
            }
            *current_ = std::move(first_);
        }
    }

    struct permutation_forward
    {

        permutation_forward(difference_type const _leader, difference_type const _size)
            : leader_(_leader)
            , current_(_leader)
            , half_size_(_size / 2)
        { ; }

        bool
        operator ++ ()
        {
            if (current_ < half_size_) {
                current_ += current_;
            } else {
                current_ = 1 + (current_ - half_size_) * 2;
            }
            return (current_ != leader_);
        }

        operator difference_type () const
        {
            return current_;
        }

    private :

        difference_type const leader_;
        difference_type current_;
        difference_type const half_size_;

    };

    struct permutation_backward
    {

        permutation_backward(difference_type const _leader, difference_type const _size)
            : leader_(_leader)
            , current_(_leader)
            , half_size_(_size / 2)
        { ; }

        bool
        operator ++ ()
        {
            if ((current_ % 2) == 0) {
                current_ /= 2;
            } else {
                current_ = (current_ - 1) / 2 + half_size_;
            }
            return (current_ != leader_);
        }

        operator difference_type () const
        {
            return current_;
        }

    private :

        difference_type const leader_;
        difference_type current_;
        difference_type const half_size_;

    };

    std::deque< difference_type > powers3_;

};
Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • I think this implementation has O(N log N) complexity because you exchange sub-arrays starting from larger one (so you move a growing sub-array on each iteration). – Evgeny Kluev Nov 09 '12 at 19:58
  • Another way is to keep the length of all the subarrays and then do backward motion with reverse function. But this violates the requirement O(log log n) memory – Tomilov Anatoliy Nov 10 '12 at 05:48
  • Or, we can calculate the (growing) length of the next small subarray every step back - it will be O (log n log n) time additionaly. – Tomilov Anatoliy Nov 10 '12 at 06:00
  • Please, tell me how to perform step 4 with O(n) time complexity and O(log log n) memory? – Tomilov Anatoliy Nov 10 '12 at 08:19
  • You just shown two ways to do it without violating any requirements. Second one, lengths recalculation on each step, requires O((log N)^3) additional time. But is is less than O(N), so the whole algorithm still has O(N) time complexity. First one, "keep the length of all the sub-arrays" should be corrected: keep only the number of sub-arrays of each size (0 .. 3), which means 2 * log N bits. You could pack these bits into a pair of integers. – Evgeny Kluev Nov 10 '12 at 08:36
  • I granted the O(n) time. This solution is pretty dirty, but quite a workable. – Tomilov Anatoliy Nov 12 '12 at 10:25
  • Your solution's iterators seem to go out-of-bounds, try running it with iterator checking enabled. – user541686 Nov 04 '13 at 02:37
  • @Mehrdad Thank you. Yes, this is the issue, but I have no time. In any case, you have given a working version (I hope) of the solution. – Tomilov Anatoliy Nov 04 '13 at 08:35
  • @Dukales: Yes -- I actually found an easier solution I wrote below this answer. :) – user541686 Nov 04 '13 at 08:39
  • I tried to check my solution with the -D_GLIBCXX_DEBUG=1 and found that the problem is only in the **backward** algorithm. So **forward** algorithm is still workable. – Tomilov Anatoliy Nov 04 '13 at 08:39
  • @Mehrdad I rewrote the solution. Now it designed only for even numbers. – Tomilov Anatoliy Jun 04 '14 at 07:33
0

I modified the code here to get this algorithm:

void PartitionIndexParity(T arr[], size_t n)
{
    using std::swap;
    for (size_t shift = 0, k; shift != n; shift += k)
    {
        k = (size_t)pow(3, ceil(log(n - shift) / log(3)) - 1) + 1;
        for (size_t i = 1; i < k; i *= 3)  // cycle-leader algorithm
        {
            size_t j = i;
            do { swap(arr[(j = j / 2 + (j % 2) * (k / 2)) + shift], arr[i + shift]); } while (j != i);
        }

        for (size_t b = shift / 2, m = shift, e = shift + (k - k / 2), i = m; shift != 0 && k != 0; )  // or just use std::rotate(arr, b, m, e)
        {
            swap(arr[b++], arr[i++]);
            if (b == m && i == e) { break; }
            if (b == m) { m = i; }
            else if (i == e) { i = m; }
        }
    }
}
user541686
  • 205,094
  • 128
  • 528
  • 886
0

Here's a Java implementation of Peiyush Jain's algorithm:

import java.util.Arrays;

public class InShuffle {
    public static void main(String[] args) {
        Integer[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

        inShuffle(nums);

        System.out.println(Arrays.toString(nums));
    }

    public static <T> void inShuffle(T[] array) {
        if (array == null) {
            return;
        }

        inShuffle(array, 0, array.length - 1);
    }

    private static <T> void inShuffle(T[] array, int startIndex, int endIndex) {
        while (endIndex - startIndex + 1 > 1) {
            int size = endIndex - startIndex + 1;
            int n = size / 2;
            int k = (int)Math.floor(Math.log(size + 1) / Math.log(3));
            int m = (int)(Math.pow(3, k) - 1) / 2;

            rotateRight(array, startIndex + m, startIndex + n + m - 1, m);

            for (int i = 0, cycleStartIndex = 0; i < k; ++i, cycleStartIndex = cycleStartIndex * 3 + 2) {
                permuteCycle(array, startIndex, cycleStartIndex, 2 * m + 1);
            }

            endIndex = startIndex + 2 * n - 1;
            startIndex = startIndex + 2 * m;
        }
    }

    private static <T> void rotateRight(T[] array, int startIndex, int endIndex, int amount) {
        reverse(array, startIndex, endIndex - amount);
        reverse(array, endIndex - amount + 1, endIndex);
        reverse(array, startIndex, endIndex);
    }

    private static <T> void reverse(T[] array, int startIndex, int endIndex) {
       for (int leftIndex = startIndex, rightIndex = endIndex; leftIndex < rightIndex; ++leftIndex, --rightIndex) {
           swap(array, leftIndex, rightIndex);
       }
    }

    private static <T> void swap(T[] array, int index1, int index2) {
        T temp = array[index1];
        array[index1] = array[index2];
        array[index2] = temp;
    }

    private static <T> void permuteCycle(T[] array, int offset, int startIndex, int mod) {
        for (int i = ((2 * startIndex + 2) % mod) - 1; i != startIndex; i = ((2 * i + 2) % mod) - 1) {
            swap(array, offset + i, offset + startIndex);
        }
    }
}

And doing an out-shuffle is as simple as:

public static <T> void outShuffle(T[] array) {
    if (array == null) {
       return;
    }

    inShuffle(array, 1, array.length - 1);
}
John Kurlak
  • 6,594
  • 7
  • 43
  • 59
0
public class OddToLeftEvenToRight {

    private static void doIt(String input){

        char[] inp = input.toCharArray();
        int len = inp.length;

        for(int j=1; j< len; j++)
        {
            for(int i=j; i<len-j; i+=2)
            {

                swap(inp, i, i+1);

            }
        }

        System.out.print(inp);

    }

    private static void swap(char[] inp, int i, int j) {

        char tmp = inp[i];
        inp[i]= inp[j];
        inp[j]=tmp;

    }

    public static void main(String[] args)
    {

        doIt("a1b");
    }

}

This program does it in O(n^2).

johnnyRose
  • 7,310
  • 17
  • 40
  • 61
Ram
  • 628
  • 1
  • 6
  • 19
0

There is a simple in-place algorithm that does exactly N swaps described here: https://stackoverflow.com/a/55112294/10396

Define a source index function to find the value that belongs at a given location in the desired result.

def index(loc, N): 
  mid = N-N//2 
  return (loc*2)+1 if loc < mid else (loc-mid)*2

then walk from beginning to the end, swapping every item with the one at the calculated index, but if that index is earlier than the current location, recalculate to see where it was swapped to.

def unshuffle(A):
    N = len(A)
    for i in range(N):
      source = index(i, N)
      while source < i:
        source = index(source,N)
      A[i],A[source] = A[source],A[i]
    return A

The number of calls to index is logarithmic, but for large arrays on real hardware, the time cost is minimal compared to the cost of the swaps.

This gives

>>> unshuffle([7, 5, 6, 3, 8, 4, 2, 1])
[5, 3, 4, 1, 7, 6, 8, 2]
AShelly
  • 34,686
  • 15
  • 91
  • 152