3

I have an array of int as input. The array will always be a length of 2^n. I want to cut the array in half and stack it. Repeat cutting and stacking until there is only one stack. For example:

int[] array = {1,2,3,4,5,6,7,8}

if we cut the array in half we and stack them it would be:

{1,2,| 3,4}
{5,6,| 7,8}

cut it and stack again:

{1,|2}
{5,|6}
{3,|4}
{7,|8}

again:

{1}
{5}
{3}
{7}
{2}
{6}
{4}
{8}

the desired output would be an array of int from the top to the end of the stack

int[] output =  {1,5,3,7,2,6,4,8}

I have tried to construct the output array by looping the input array in a particular way. Note that when I reach the array I just start from the head again. I start at the array[i] where i = 0. I get the first number this way. then I increment i by n where n is the log(array.legnth) (base 2). This is how I get the second number. For the third number, we increment i by (n + n/2). For the fourth number, we increment i by n again. I am wondering is there a pattern? Or what would be your approach to solve this problem? I am looking for a solution in java or python.


Edit/Update:

I tried a new approach using queue. I basically keep cutting array in half and push both half of array into queue until arrays in queue all have length of 2 (or the stack is at height n). but my result is not correct. I think it has to do with the order I add the half arrays back into the queue.

import java.util.*;

public class StackArray{
    public static void main(String[] args){
        int[] array = {1,2,3,4,5,6,7,8};
        int[] answer = stackArray(array);
        for(int n : answer){
            System.out.println(n);
        }   
    }   

    public static int[] stackArray(int[] array){
        int height = (int) (Math.log(array.length)/Math.log(2)) + 1;
        Queue<int[]> queue = new LinkedList<int[]>();
        ArrayList<Integer> list = new ArrayList<>();
        queue.add(array);
        while(queue.size() < height){
            int currentLength = queue.size();
            int i = 0;
            while(i < currentLength){
                int[] temp = queue.poll();
                int[] array1 = new int[temp.length/2];
                int[] array2 = new int[temp.length/2];
                System.arraycopy(temp, 0, array1, 0, array1.length);
                System.arraycopy(temp, array1.length, array2, 0, array2.length);
                queue.add(array1); //I think the problem is here
                queue.add(array2);
                i++;
            }

        }


        int y = 0;
        while(y < 2){

            for(int i = 0; i < queue.size(); i++){
                int[] curr = queue.poll();
                list.add(curr[y]);
                queue.add(curr);

            }
            y++;
        }

        int[] ret = new int[list.size()];
        for(int i = 0; i < list.size(); i++){
            ret[i] =list.get(i);
        }

        return ret;

    }
}

result:

1
3
5
7
2
4
6
8

how would I fix this?


update: I solved it and posted my own answer. but I am still curious as of how would other people solve this. Please stil feel free to answer.

OLIVER.KOO
  • 5,654
  • 3
  • 30
  • 62
  • Please pick *one* language. Then edit your question to have that language as a tag, and also include a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) of what you have tried together with a description of how it didn't work as expected. And if you haven't done it recently, then please take some time to [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask) again. – Some programmer dude Sep 13 '17 at 06:28

2 Answers2

6

I think the pattern becomes clear if you use 0-based indices and express numbers in binary. e.g

       0    1    2    3    4    5    6   7
      000  001  010  011  100  101  110  111

       0    1    2    3
      000  001  010  011
      100  101  110  111
       4    5    6    7


  0 = 000  001 = 1 
  4 = 100  101 = 5
  2 = 010  011 = 3
  6 = 110  111 = 7

  0 = 000  
  4 = 100
  2 = 010
  6 = 110
  1 = 001
  5 = 101
  3 = 011
  7 = 111

see the pattern in the left-most bits? the sequence is just the numbers 0,1,2 .. with the bit order reversed.

jq170727
  • 13,159
  • 3
  • 46
  • 56
  • ah! but what if the input array is not `{1,2,3,4,5,6,7,8}` but some random positive whole number? `{12,5,8,9,156,55,78,12}`? then it wouldn't work in this case I think – OLIVER.KOO Sep 13 '17 at 07:06
  • Just use the indices. – jq170727 Sep 13 '17 at 07:06
  • I was about to delete my comment. cause I realize they are indices. This is a very unique solution. how did you come up with it? – OLIVER.KOO Sep 13 '17 at 07:08
  • Problems involving powers of 2 are often easier to solve in binary :-) – jq170727 Sep 13 '17 at 07:20
  • +1 awesome! I want to see if there are any other approach to solve this problem. so I am going to wait until later tonight to mark your answer as the solution. Thanks! – OLIVER.KOO Sep 13 '17 at 14:01
1

I solved it using two artillery queues and a main queue:

import java.util.*;

public class StackArray{
    public static void main(String[] args){
        int[] array = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
        int[] answer = stackArray(array);
        for(int n : answer){
            System.out.println(n);
        }   
    }   

    public static int[] stackArray(int[] array){
        int height = (int) (Math.log(array.length)/Math.log(2)) + 1;
        Queue<int[]> queue = new LinkedList<int[]>();
        ArrayList<Integer> list = new ArrayList<>();
        Queue<int[]> queue1 = new LinkedList<int[]>();
        Queue<int[]> queue2 = new LinkedList<int[]>();
        queue.add(array);
        while(queue.size() < height){
            int currentLength = queue.size();

            int i = 0;
            while(!queue.isEmpty()){
                int[] temp = queue.poll();
                int[] array1 = new int[temp.length/2];
                int[] array2 = new int[temp.length/2];
                System.arraycopy(temp, 0, array1, 0, array1.length);
                System.arraycopy(temp, array1.length, array2, 0, array2.length);
                queue1.add(array1); //I think the problem is here
                queue2.add(array2);
                i++;
            }
            while(!queue1.isEmpty()){
                int[] temp1 = queue1.poll();    
                queue.add(temp1);   
            }
            while(!queue2.isEmpty()){
                int[] temp2 = queue2.poll();
                queue.add(temp2);
            }

        }


        int y = 0;
        while(y < 2){

            for(int i = 0; i < queue.size(); i++){
                int[] curr = queue.poll();
                list.add(curr[y]);
                queue.add(curr);

            }
            y++;
        }

        int[] ret = new int[list.size()];
        for(int i = 0; i < list.size(); i++){
            ret[i] =list.get(i);
        }

        return ret;

    }
}

output;

1
5
3
7
2
6
4
8

also test on when n = 4:

1
9
5
13
3
11
7
15
2
10
6
14
4
12
8
16
OLIVER.KOO
  • 5,654
  • 3
  • 30
  • 62