ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] 배열 회전하기
    Java/유틸 2024. 9. 17. 16:52
    반응형

    자바에서는 배열을 회전시키는 여러 가지 방법이 있습니다. 전통적인 for 문, 스트림 API, 그리고 헬퍼 메서드를 사용하는 방법이 있습니다.

     

    1. 반복문을 사용하여 배열을 회전

    전통적인 for 문를 사용하여 배열을 회전하는 방법은 직관적이고 간단합니다.

    /**
     * 반복문을 사용하여 배열을 회전
     *
     * @param nums 회전할 배열
     * @param k    회전할 위치 수
     * @return 회전된 배열
     */
    public int[] rotateWithLoop(int[] nums, int k) {
      int n = nums.length;
      if (n == 0) {
        return nums;
      }
      k = k % n;
      int[] rotated = new int[n];
    
      for (int i = 0; i < n; i++) {
        rotated[(i + k) % n] = nums[i];
      }
    
      return rotated;
    }

    단위 테스트

    @Order(1)
    @DisplayName("rotateWithLoop: 배열 회전")
    @Test
    void testRotateWithLoop() {
    
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithLoop(nums, 3);
    
      // Then
      int[] expected = {5, 6, 7, 1, 2, 3, 4};
      assertArrayEquals(expected, result);
    }
    
    @Order(2)
    @DisplayName("rotateWithLoop: 빈 배열 테스트")
    @Test
    void testRotateWithLoopEmptyArray() {
    
      // Given
      int[] nums = {};
    
      // When
      int[] result = arrayRotation.rotateWithLoop(nums, 3);
    
      // Then
      int[] expected = {};
      assertArrayEquals(expected, result);
    }
    
    @Order(3)
    @DisplayName("rotateWithLoop: 단일 요소 배열 회전")
    @Test
    void testRotateWithLoopSingleElement() {
    
      // Given
      int[] nums = {1};
    
      // When
      int[] result = arrayRotation.rotateWithLoop(nums, 3);
    
      // Then
      int[] expected = {1};
      assertArrayEquals(expected, result);
    }
    
    @Order(4)
    @DisplayName("rotateWithLoop: 회전을 하지 않는 경우 테스트")
    @Test
    void testRotateWithLoopZeroTimes() {
    
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithLoop(nums, 0);
    
      // Then
      int[] expected = {1, 2, 3, 4, 5, 6, 7};
      assertArrayEquals(expected, result);
    }
    
    @Order(5)
    @DisplayName("rotateWithLoop: 배열 길이보다 많은 회전 테스트")
    @Test
    void testRotateWithLoopMoreThanLength() {
    
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithLoop(nums, 10);
    
      // Then
      int[] expected = {5, 6, 7, 1, 2, 3, 4};
      assertArrayEquals(expected, result);
    }

     

    장점
    - 직관성 : 단순하고 이해하기 쉽습니다.

    단점
    - 코드 길이 : 더 복잡한 경우 코드가 길어질 수 있습니다.

     

    2. Stream API를 사용하여 배열을 회전

    Java 8부터 도입된 스트림 API를 사용하면 더 간결하고 함수형 프로그래밍 스타일의 코드를 작성할 수 있습니다.

    /**
     * 스트림을 사용하여 배열을 회전
     *
     * @param nums 회전할 배열
     * @param k    회전할 위치 수
     * @return 회전된 배열
     */
    public int[] rotateWithStreams(int[] nums, int k) {
      int n = nums.length;
      if (n == 0) {
        return nums;
      }
      k = k % n;
      final int finalK = k;
    
      return IntStream.range(0, n)
          .map(i -> nums[(i + (n - finalK)) % n])
          .toArray();
    }

    단위 테스트

    @Order(6)
    @DisplayName("rotateWithStreams: 배열 회전")
    @Test
    void testRotateWithStreams() {
    
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithStreams(nums, 3);
    
      // Then
      int[] expected = {5, 6, 7, 1, 2, 3, 4};
      assertArrayEquals(expected, result);
    }
    
    @Order(7)
    @DisplayName("rotateWithStreams: 빈 배열 테스트")
    @Test
    void testRotateWithStreamsEmptyArray() {
    
      // Given
      int[] nums = {};
    
      // When
      int[] result = arrayRotation.rotateWithStreams(nums, 3);
    
      // Then
      int[] expected = {};
      assertArrayEquals(expected, result);
    }
    
    @Order(8)
    @DisplayName("rotateWithStreams: 단일 요소 배열 회전")
    @Test
    void testRotateWithStreamsSingleElement() {
    
      // Given
      int[] nums = {1};
    
      // When
      int[] result = arrayRotation.rotateWithStreams(nums, 3);
    
      // Then
      int[] expected = {1};
      assertArrayEquals(expected, result);
    }
    
    @Order(9)
    @DisplayName("rotateWithStreams: 회전을 하지 않는 경우 테스트")
    @Test
    void testRotateWithStreamsZeroTimes() {
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithStreams(nums, 0);
    
      // Then
      int[] expected = {1, 2, 3, 4, 5, 6, 7};
      assertArrayEquals(expected, result);
    }
    
    @Order(10)
    @DisplayName("rotateWithStreams: 배열 길이보다 많은 회전 테스트")
    @Test
    void testRotateWithStreamsMoreThanLength() {
    
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithStreams(nums, 10);
    
      // Then
      int[] expected = {5, 6, 7, 1, 2, 3, 4};
      assertArrayEquals(expected, result);
    }

     

    장점
    - 가독성 : 코드가 매우 간결하고 읽기 쉽습니다.
    - 함수형 프로그래밍 : 최신 자바에서 선호되는 함수형 프로그래밍 패러다임을 활용합니다.

    단점 :
    - 성능 오버헤드 : 스트림은 약간의 성능 오버헤드를 수반할 수 있습니다.

     

    3. 헬퍼 메서드를 사용하여 배열을 회전

    헬퍼 메서드를 사용하여 배열을 회전시키는 방법은 배열을 역순으로 뒤집어 회전 효과를 얻을 수 있습니다.

    /**
     * 헬퍼 메서드를 사용하여 배열을 회전시킵니다. 배열을 역순으로 뒤집는 방법을 사용
     *
     * @param nums 회전할 배열
     * @param k    회전할 위치 수
     * @return 회전된 배열
     */
    public int[] rotateWithHelperMethods(int[] nums, int k) {
      int n = nums.length;
      if (n == 0) {
        return nums;
      }
      k = k % n;
    
      int[] result = nums.clone();
      reverse(result, 0, n - 1);
      reverse(result, 0, k - 1);
      reverse(result, k, n - 1);
    
      return result;
    }
    
    /**
     * 배열의 일부를 뒤집는 헬퍼 메서드
     *
     * @param nums  회전할 배열
     * @param start 뒤집을 시작 인덱스
     * @param end   뒤집을 끝 인덱스
     */
    private void reverse(int[] nums, int start, int end) {
      while (start < end) {
        int temp = nums[start];
        nums[start] = nums[end];
        nums[end] = temp;
        start++;
        end--;
      }
    }

    단위 테스트

    @Order(11)
    @DisplayName("rotateWithHelperMethods: 배열 회전")
    @Test
    void testRotateWithHelperMethodsBasic() {
    
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithHelperMethods(nums, 3);
    
      // Then
      int[] expected = {5, 6, 7, 1, 2, 3, 4};
      assertArrayEquals(expected, result);
    }
    
    @Order(12)
    @DisplayName("rotateWithHelperMethods: 빈 배열 테스트")
    @Test
    void testRotateWithHelperMethodsEmptyArray() {
    
      // Given
      int[] nums = {};
    
      // When
      int[] result = arrayRotation.rotateWithHelperMethods(nums, 3);
    
      // Then
      int[] expected = {};
      assertArrayEquals(expected, result);
    }
    
    @Order(13)
    @DisplayName("rotateWithHelperMethods: 단일 요소 배열 회전")
    @Test
    void testRotateWithHelperMethodsSingleElement() {
    
      // Given
      int[] nums = {1};
    
      // When
      int[] result = arrayRotation.rotateWithHelperMethods(nums.clone(), 3);
    
      // Then
      int[] expected = {1};
      assertArrayEquals(expected, result);
    }
    
    @Order(14)
    @DisplayName("rotateWithHelperMethods: 회전을 하지 않는 경우 테스트")
    @Test
    void testRotateWithHelperMethodsZeroTimes() {
    
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithHelperMethods(nums.clone(), 0);
    
      // Then
      int[] expected = {1, 2, 3, 4, 5, 6, 7};
      assertArrayEquals(expected, result);
    }
    
    @Order(15)
    @DisplayName("rotateWithHelperMethods: 배열 길이보다 많은 회전 테스트")
    @Test
    void testRotateWithHelperMethodsMoreThanLength() {
    
      // Given
      int[] nums = {1, 2, 3, 4, 5, 6, 7};
    
      // When
      int[] result = arrayRotation.rotateWithHelperMethods(nums.clone(), 10);
    
      // Then
      int[] expected = {5, 6, 7, 1, 2, 3, 4};
      assertArrayEquals(expected, result);
    }

     

    장점

    - 효율성 : 추가 배열 저장소 없이 배열 회전이 가능합니다.

    단점
    - 복잡성 : 세 단계로 배열을 뒤집어야 하므로 직관적이지 않을 수 있습니다.

     

    결론

    결론적으로, 자바에서 배열 회전을 구현하는 방법은 다양합니다. 상황에 따라 가장 적합한 방법을 선택하여 사용할 수 있습니다. 일반적으로 스트림 API는 간결성과 가독성 측면에서 많이 선호되며, 전통적인 for 문 또한 여전히 널리 사용됩니다. 더 복잡한 회전 로직이 필요한 경우 헬퍼 메서드를 사용하는 것이 효율적일 수 있습니다.

     

    소스 코드는 Github Repository- https://github.com/tychejin1218/blog/tree/main/java-util 프로젝트를 참조하세요.

    반응형

    'Java > 유틸' 카테고리의 다른 글

    [JAVA] 배열의 중복 요소 제거하기  (2) 2024.09.17
    [JAVA] 배열의 합 구하기  (1) 2024.09.17
    [JAVA] 배열 검색하기  (0) 2024.09.17
    [JAVA] 배열 정렬하기 : 오름차순, 내림차순  (1) 2024.09.17

    댓글

Designed by Tistory.