Algorithm/Rotate Array

[Practice Algorithm, GeeksForGeeks] Rotate Array2

Tree_Park 2020. 11. 11. 21:37
728x90

저번에 포스팅한 rotate Array와 비슷한 문제를 풀어보았다.

 

practice.geeksforgeeks.org/problems/rotate-array-by-n-elements/1#

 

Rotate Array | Practice | GeeksforGeeks

 

practice.geeksforgeeks.org

 


문제

Given an array of size N. The task is to rotate array by D elements where  N.

 

Example 1:

Input:

    N = 7

    Arr[] = {1, 2, 3, 4, 5, 6, 7}

    D = 2

    Output: 3 4 5 6 7 1 2

Explanation:

    Rotate by 1: [2, 3, 4, 5, 6, 7, 1]

    Rotate by 2: [3, 4, 5, 6, 7, 1, 2]

 

Expected Time Complexity: O(N)
Expected Auxiliary Space: O(1)


Constraints:
1 ≤ N ≤ 105
1 ≤ Arr[i] ≤ 1000
0 ≤ D ≤ N


코드

package rotate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.stream.Collectors;

public class ReversalRotateArray {

	public static void leftRotate(Integer[] arr, int n, int d) {
		int temp = arr[0];
		int[] tempArr = new int[n];
		int index = 0, count = 0;
		
		
		if(n==d) return;
			for (int i = d; count < n; i++, count++) {
				tempArr[count] = arr[i%n];
			}
			count = 0;
			while (index < n) {
				if (index < n-d) {
					temp = arr[index];
					arr[index] = tempArr[index];
					tempArr[index] = temp;
					count++;
				}						
				if (index >= n-d) {
					arr[index] = tempArr[count++];
				}		
				index++;
			}			
	}

	public static void printArray(Integer[] arr) {
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("[");
		for (int i = 0; i < arr.length; i++) {
			if (i == arr.length - 1) {
				stringBuilder.append(arr[i] + "]");
				break;
			}
			stringBuilder.append(arr[i] + ", ");
		}
		System.out.println(stringBuilder.toString());
	}

	public static void main(String[] args) {
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
		try {
			int n = Integer.parseInt(bufferedReader.readLine());
			Integer[] arr = new Integer[n];
			Arrays.stream(bufferedReader.readLine().split(" ")).map(s -> Integer.parseInt(s))
					.collect(Collectors.toList()).toArray(arr);

			int d = Integer.parseInt(bufferedReader.readLine());

			leftRotate(arr, n, d);
			printArray(arr);

		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

처음에는 당연히 저번에 풀었던 방식으로 비슷하게 풀어보았지만.

시간 초과해버렸다.

내 코드의 불합리함에 절망해버렸다. 시간을 줄이기 위해 여러 자료구조를 사용하는 방법이 생각났지만, 이 챕터에서는 아직 다른 자료구조를 배우지 않은 상태임으로, 좀 더 고집을 부려보기로 했다.

하지만, 코드를 보던 중, n==d일때의 경우를 생각해보았다. 결국에는 1,2,3,4,5,6,7의 배열이 주어질 경우, rotate를 수행하여도, 1,2,3,4,5,6,7의 결과를 보이기 때문에, 이 조건식만 추가해 보았다.

public static void leftRotate(Integer[] arr, int n, int d) {
		int temp = arr[0];
		int[] tempArr = new int[n];
		int index = 0, count = 0;
		
		
		if(n==d) return;
			for (int i = d; count < n; i++, count++) {
				tempArr[count] = arr[i%n];
			}
			count = 0;
			while (index < n) {
				if (index < n-d) {
					temp = arr[index];
					arr[index] = tempArr[index];
					tempArr[index] = temp;
					count++;
				}						
				if (index >= n-d) {
					arr[index] = tempArr[count++];
				}		
				index++;
			}			
	}

띠용.. 성공해버렸다.

 


내가 practice를 자랑스럽게 풀어보았음으로, 문제에서는 어떻게 풀었는지 확인해 보았다.

 예제로 나온 코드

// Java program for reversal algorithm of array rotation 
import java.io.*; 
  
class LeftRotate { 
    /* Function to left rotate arr[] of size n by d */
    static void leftRotate(int arr[], int d) 
    { 
  
        if (d == 0) 
            return; 
  
        int n = arr.length; 
        // in case the rotating factor is 
        // greater than array length 
        d = d % n; 
        reverseArray(arr, 0, d - 1); 
        reverseArray(arr, d, n - 1); 
        reverseArray(arr, 0, n - 1); 
    } 
  
    /*Function to reverse arr[] from index start to end*/
    static void reverseArray(int arr[], int start, int end) 
    { 
        int temp; 
        while (start < end) { 
            temp = arr[start]; 
            arr[start] = arr[end]; 
            arr[end] = temp; 
            start++; 
            end--; 
        } 
    } 
  
    /*UTILITY FUNCTIONS*/
    /* function to print an array */
    static void printArray(int arr[]) 
    { 
        for (int i = 0; i < arr.length; i++) 
            System.out.print(arr[i] + " "); 
    } 
  
    /* Driver program to test above functions */
    public static void main(String[] args) 
    { 
        int arr[] = { 1, 2, 3, 4, 5, 6, 7 }; 
        int n = arr.length; 
        int d = 2; 
  
        leftRotate(arr, d); // Rotate array by d 
        printArray(arr); 
    } 
} 
/*This code is contributed by Devesh Agrawal*/

아, 저렇게도 풀수 있구나..

N=7, arr=[1,2,3,4,5,6,7], D=2일 경우

reverseArray(arr, 0, 2- 1);

    // [1,2,3,4,5,6,7] → [2,1,3,4,5,6,7]

reverseArray(arr, 2, 6); 

    // [2,1,3,4,5,6,7] [2,1,7,6,5,4,3]

reverseArray(arr, 0, 6);

   //  [2,1,7,6,5,4,3] → [3,4,5,6,7,1,2]

 

진행된것을 보았는데도 신박한 느낌이다.

결과도 한 번 봐볼까?

 

2.39! 0.01초 차이로 승리했다 ㅎㅎ

결과


😒 input data 적용은 저번 코드를 그대로 참고했다.

🤔 그리고 Example2가 문제에 명시되어있는데 예상되는 결과가 실제 코드에서 수행되는 결과와 다르다.

🤢 Example2를 보고, 아! d+1==n 이면 rightRotate가 수행되는건가 하면서, 코드를 수정해보았지만 웬걸, 시간낭비만 했다.

😜 Example2는 왜 두신거죠? 스앵님

 

* 위에서 제시한 코드 이외에도 여러 방법이 나와있고, 각각 친절하게 원리와 시간복잡도 및 공간복잡도가 명시되어있으니 필요하면 직접 사이트에서 봐보는것을 추천한다.

www.geeksforgeeks.org/array-rotation/

 

Program for array rotation - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org