简体   繁体   中英

Rotate Array by k

Given an array and a number k we have to rotate array k times.

Sample Input
1            //number of of testcases 
5 2          //5(array size) 2(K value)
1 2 3 4 5    /array elements
Sample output
4 5 1 2 3

Here is my code

import java.util.*;
class TestClass {
    public static void main(String args[] ) throws Exception {
        // Write your code here
        Scanner input=new Scanner(System.in);
        int testcases=input.nextInt();

        for(int i=0;i<testcases;i++)
        {
            int size=input.nextInt();
            int rotationNo=input.nextInt();
            rotateArray(size, rotationNo, input);
        }
    }
    public static void rotateArray(int size, int rotationNo, Scanner input)
    {
        int[] arr=new int[size];
        int[] result=new int[size];

        rotationNo=rotationNo%size;

        for(int i=0;i<size;i++)
        {
            arr[i]=input.nextInt();
        }

        int resultIndex=0;

        int index=size-rotationNo;

        int k=index,t=0,track=0;

        while(true)
        {
            if(k<size)
            {
                System.out.print(arr[k++]+" ");
                ++track;

                if(track==size)
                {
                    break;
                }
                else
                {
                    continue;
                }
            }
            if(t<index)
            {
                if(t==(index-1))
                {
                    System.out.print(arr[t++]);
                }
                else
                {    
                    System.out.print(arr[t++]+" ");
                }
                ++track;
                
                if(track==size)
                {
                    break;
                }
                else
                {
                    continue;
                }
            }
        }

        System.out.println();
    }
}

This question was asked in a programming competition. My all testcases were passing except one which showed time limit exceeded. But I am not understanding what is the cause of time limit exceed. Loops will always halt whatever be the testcase. Time Complexity of my code is O(n). Is there another better and efficient solution?

Start outputting the input directly (ie without storing it) as soon as k values have been read and stored.
Then output the k initially read and stored values.

The shifting inside the array, is the relevant operation here.
The fewer shifts are done (the distance of shifting is not really relevant here, if implemented correctly), the better. It includes the storing and retrieving to/from an array. I consider the reading and outputting, if done without any processing in between, to be negligible. Ie I focus on the shifting.

Strictly speaking, the reading and outputting is processing and that would mean that no improvement of O() can be calculated.

But allow me to ignore the reading and outputting for an O() estimation of the improvement:

The proposed recommendation will improve the number of array-accesses during shifting from O(n) to O(k). Admittedly the reading and outputting is ignored here. Storing and retrieving from an array and especially the shifting inside the array is avoided here and that is the O(k) part which is relevant here.
So the relevant operations are O(k), ignoring nk values in O(1).

A test case like

1
10000 1
1 2 3 4 5 6 7 8 ...

will easily eliminate programs which after reading and before outputting, do O(4*10000) , ie store all, read and write all for shifting and then read all for outputting. Compared to O(2*1) for only storing a single value and reading again for outputting at the end.
(Yes, I know clean O() analysis does not use factors, or any digits. You stil get the point, I hope. ;-)

Here is a code proposal (simplified to a single testcase):

import java.util.*;
public class Test {

    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);
        int testcases= input.nextInt(); //ignored, assuming 1
        int size     = input.nextInt();
        int rotation = input.nextInt();
        int i=0;

        int[] newArr = new int[rotation%size]; //small array
        // based on the nice idea by User-Upvotedon'tsayThanks
        
        for(; i<rotation%size; i++)
        {
            newArr[i] = input.nextInt(); // few write accesses
        }
        for(; i<size; i++)
        {
            System.out.println( input.nextInt()); //many direct outpots
        }
        for(i=0; i<rotation%size; i++)
        {
            System.out.println(newArr[i]); // few outputs from array
        }
        return;
    }
}

For an input of:

1
5 2
1 2 3 4 5

It gets you an output of:

3
4
5
1
2

Same output for a modulo-requiring input of:

1
5 7
1 2 3 4 5

I have provided a solution below which will directly output the scanner input up until the size of input has been met. It has a constant time o(n) for input, however it only touches each item once. and avoids the use of a while loop that may otherwise increase the multiplier of the iterations.


public class Test {


    public static void main(String[] args) {

        int rotation = new Scanner(System.in).nextInt();
        int size = new Scanner(System.in).nextInt();


        int[] values = rotate(rotation, size, new Scanner(System.in));

        for(int i : values){
            System.out.println(i);
        }
    }

    public static int[] rotate(int rotation, int size, Scanner input){

        int[] newArr = new int[size];

        for(int i = 0; i<size; i++){

            int newPosition = i + rotation;

            newPosition = newPosition >= size ? newPosition - size : newPosition;

            newArr[newPosition] = input.nextInt();

        }

        return newArr;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM