N Log

프로그래머스 입문 120844 배열 회전시키기

문제

출처

배열의 원소를 direction 방향으로 한 칸씩 회전시키시오.

numbers direction result
[1, 2, 3] “right” [3, 1, 2]
[4, 455, 6, 4, -1, 45, 6] “left” [455, 6, 4, -1, 45, 6, 4]

풀이

[1, 2, 3]을 오른쪽으로 회전시키면 각 원소의 인덱스는 다음처럼 바뀐다.

0 -> 1
1 -> 2
2 -> 0

2 -> 0처럼 마지막 원소가 처음으로 돌아가는 경우를 제외하면, 원본 배열의 n번 인덱스 값은 결과 배열의 n + 1번 인덱스로 이동한다.

[4, 455, 6, 4, -1, 45, 6]을 왼쪽으로 회전시키면 각 원소의 인덱스는 다음처럼 바뀐다.

0 -> 6
1 -> 0
2 -> 1
3 -> 2
4 -> 3
5 -> 4
6 -> 5

0 -> 6처럼 첫 원소가 마지막으로 돌아가는 경우를 제외하면, 원본 배열의 n번 인덱스 값은 결과 배열의 n - 1번 인덱스로 이동한다.

방향별로 한 칸씩 옮기기

#include <stdlib.h>
#include <string.h>

int* solution(int numbers[], size_t numbers_len, const char* direction)
{
    int* result = (int*)malloc(sizeof(int) * numbers_len);

    if (strcmp(direction, "right") == 0)
    {
        for (int i = 0; i < numbers_len - 1; i++)
        {
            result[i + 1] = numbers[i];
        }

        result[0] = numbers[numbers_len - 1];
    }
    else
    {
        for (int i = 1; i < numbers_len; i++)
        {
            result[i - 1] = numbers[i];
        }

        result[numbers_len - 1] = numbers[0];
    }

    return result;
}

위에서 설명한 인덱스 이동 규칙을 그대로 코드로 옮긴 것이다.

오른쪽으로 회전할 때는 원본 배열의 i번 인덱스 값을 결과 배열의 i + 1번 인덱스에 대입한다.
원본 배열의 마지막 값은 결과 배열의 첫 번째 칸으로 돌아가야 하므로 따로 처리한다.

왼쪽으로 회전할 때는 원본 배열의 i번 인덱스 값을 결과 배열의 i - 1번 인덱스에 대입한다.
원본 배열의 첫 번째 값은 결과 배열의 마지막 칸으로 돌아가야 하므로 따로 처리한다.

나머지 연산으로 순환 위치 구하기

#include <stdlib.h>
#include <string.h>

int* solution(int numbers[], size_t numbers_len, const char* direction)
{
    int* result = (int*)malloc(sizeof(int) * numbers_len);

    if (strcmp(direction, "right") == 0)
    {
        for (int i = 0; i < numbers_len; i++)
        {
            result[(i + 1) % numbers_len] = numbers[i];
        }
    }
    else
    {
        for (int i = 0; i < numbers_len; i++)
        {
            result[i] = numbers[(i + 1) % numbers_len];
        }
    }

    return result;
}

이전 방법은 대부분의 원소를 한 칸씩 옮긴 뒤, 범위를 벗어나는 값만 따로 처리했다.
그래서 오른쪽 회전에서는 마지막 원소를, 왼쪽 회전에서는 첫 번째 원소를 따로 다루는 코드가 필요했다.
나머지 연산자를 사용하면 범위를 벗어나는 인덱스도 다시 유효한 인덱스로 바꿀 수 있다.

오른쪽으로 회전할 때는 결과 배열의 인덱스를 (i + 1) % numbers_len으로 계산한다.
그러면 i + 1이 배열의 길이와 같아지는 순간 나머지가 0이 되어 마지막 값이 첫 번째 칸으로 들어간다.

왼쪽으로 회전할 때는 결과 배열의 i번 인덱스에 원본 배열의 (i + 1) % numbers_len번 인덱스 값을 넣는다.
그러면 마지막 인덱스에서 다음 값을 가져오려고 할 때 나머지가 0이 되어 원본 배열의 첫 번째 값을 가져올 수 있다.