프로그래머스 입문 120844 배열 회전시키기
문제
정수 배열 numbers, 배열의 길이 numbers_len, 회전 방향 direction("left" 또는 "right")이 주어진다.
배열의 원소를 direction 방향으로 한 칸씩 회전시키시오.
| numbers | direction | result |
|---|---|---|
| [1, 2, 3] | “left” | [2, 3, 1] |
| [4, 5, 6] | “right” | [6, 4, 5] |
풀이
[1, 2, 3]을 왼쪽으로 회전시키면 원소는 다음과 같이 이동한다.
1 2 3
/ /
2 3 1
첫 번째 원소 1은 마지막 칸으로 이동하고, 나머지 원소는 한 칸씩 앞으로 이동한다.
[4, 5, 6]을 오른쪽으로 회전시키면 원소는 다음과 같이 이동한다.
4 5 6
\ \
6 4 5
마지막 원소 6은 첫 번째 칸으로 이동하고, 나머지 원소는 한 칸씩 뒤로 이동한다.
직접 인덱스를 지정해 회전하기
#include <stdlib.h>
#include <string.h>
int* solution(int numbers[], size_t numbers_len, const char* direction)
{
int* result = malloc(sizeof(int) * numbers_len);
if (strcmp(direction, "left") == 0)
{
for (size_t i = 0; i < numbers_len - 1; i++)
{
result[i] = numbers[i + 1];
}
result[numbers_len - 1] = numbers[0];
}
else // direction == "right"
{
for (size_t i = 0; i < numbers_len - 1; i++)
{
result[i + 1] = numbers[i];
}
result[0] = numbers[numbers_len - 1];
}
return result;
}
위에서 설명한 인덱스 이동 규칙을 코드로 옮긴 구현이다.
그림에서 /와 \로 표시한 이동은 같은 규칙이 반복되므로 반복문에서 처리한다.
반복문은 배열 안에서 한 칸씩 이동하는 원소를 처리하고, 한쪽 끝에서 다른 쪽 끝으로 이동하는 원소는 따로 처리한다.
따라서 왼쪽 회전에서는 첫 번째 원소를 마지막 칸에, 오른쪽 회전에서는 마지막 원소를 첫 번째 칸에 저장한다.
나머지 연산을 이용해 회전하기
#include <stdlib.h>
#include <string.h>
int* solution(int numbers[], size_t numbers_len, const char* direction)
{
int* result = malloc(sizeof(int) * numbers_len);
if (strcmp(direction, "left") == 0)
{
for (size_t i = 0; i < numbers_len; i++)
{
result[i] = numbers[(i + 1) % numbers_len];
}
}
else // direction == "right"
{
for (size_t i = 0; i < numbers_len; i++)
{
result[(i + 1) % numbers_len] = numbers[i];
}
}
return result;
}
이전 방법은 대부분의 원소를 한 칸씩 옮긴 뒤, 범위를 벗어나는 값만 따로 처리했다.
그래서 왼쪽 회전에서는 첫 번째 원소를, 오른쪽 회전에서는 마지막 원소를 따로 처리하는 코드가 필요했다.
나머지 연산자를 사용하면 범위를 벗어나는 인덱스도 다시 유효한 인덱스로 바꿀 수 있다.
왼쪽 회전에서 i가 2이고 numbers_len이 3이면 (i + 1) % numbers_len은 (2 + 1) % 3, 즉 0이다.
따라서 numbers[0]의 원소가 result[2]에 저장된다.
오른쪽 회전에서 i가 2이고 numbers_len이 3이면 (i + 1) % numbers_len은 (2 + 1) % 3, 즉 0이다.
따라서 numbers[2]의 원소가 result[0]에 저장된다.